diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 0e503340..a41326cb 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -14,6 +14,6 @@ assignees: '' - 此处展开您咨询内容的描述 **注意事项** -- 技术咨询前请先认真阅读readme, [wiki](https://github.com/xia-chu/ZLMediaKit/wiki),如有必要,您也可以同时搜索已经答复的issue,如果没找到答案才在此提issue +- 技术咨询前请先认真阅读readme, [wiki](https://github.com/ZLMediaKit/ZLMediaKit/wiki),如有必要,您也可以同时搜索已经答复的issue,如果没找到答案才在此提issue - 技术咨询不属于bug缺陷,要求用户先star(收藏)本项目,否则会直接关闭issue diff --git a/3rdpart/CMakeLists.txt b/3rdpart/CMakeLists.txt index c90129d3..f55fc6c7 100644 --- a/3rdpart/CMakeLists.txt +++ b/3rdpart/CMakeLists.txt @@ -47,7 +47,7 @@ set(MediaServer_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/media-server") # TODO: 补一个函数处理各种库 # 添加 mov、flv 库用于 MP4 录制 -if (ENABLE_MP4 OR ENABLE_HLS_FMP4) +if (ENABLE_MP4) # MOV set(MediaServer_MOV_ROOT ${MediaServer_ROOT}/libmov) aux_source_directory(${MediaServer_MOV_ROOT}/include MOV_SRC_LIST) @@ -80,10 +80,6 @@ if (ENABLE_MP4 OR ENABLE_HLS_FMP4) message(STATUS "ENABLE_MP4 defined") update_cached_list(MK_COMPILE_DEFINITIONS ENABLE_MP4) endif () - if (ENABLE_HLS_FMP4) - message(STATUS "ENABLE_HLS_FMP4 defined") - update_cached_list(MK_COMPILE_DEFINITIONS ENABLE_HLS_FMP4) - endif () endif () # 添加 mpeg 用于支持 ts 生成 @@ -151,6 +147,17 @@ if(HAVE_RECVMMSG_API) list(APPEND COMPILE_DEFINITIONS HAVE_RECVMMSG_API) endif() +# check the socket buffer size set by the upper cmake project, if it is set, use the setting of the upper cmake project, otherwise set it to 256K +# if the socket buffer size is set to 0, it means that the socket buffer size is not set, and the kernel default value is used(just for linux) +if(DEFINED SOCKET_DEFAULT_BUF_SIZE) + if (SOCKET_DEFAULT_BUF_SIZE EQUAL 0) + message(STATUS "Socket default buffer size is not set, use the kernel default value") + else() + message(STATUS "Socket default buffer size is set to ${SOCKET_DEFAULT_BUF_SIZE}") + endif () + add_definitions(-DSOCKET_DEFAULT_BUF_SIZE=${SOCKET_DEFAULT_BUF_SIZE}) +endif() + set(ToolKit_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/ZLToolKit) # 收集源代码 file(GLOB ToolKit_SRC_LIST diff --git a/3rdpart/ZLToolKit b/3rdpart/ZLToolKit index ad44a16c..9a545d7d 160000 --- a/3rdpart/ZLToolKit +++ b/3rdpart/ZLToolKit @@ -1 +1 @@ -Subproject commit ad44a16c99834540b397774ad6c7f3f8ed619d56 +Subproject commit 9a545d7d09fc4b570c1d29a798622c7923111735 diff --git a/3rdpart/assert.h b/3rdpart/assert.h index 9b7254ff..0f293fc2 100644 --- a/3rdpart/assert.h +++ b/3rdpart/assert.h @@ -1,9 +1,9 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/AUTHORS b/AUTHORS index c26bfefb..971b41f2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -87,4 +87,14 @@ WuPeng [Deepslient](https://github.com/Deepslient) [imp_rayjay](https://github.com/rayjay214) [ArmstrongCN](https://github.com/ArmstrongCN) -[leibnewton](https://github.com/leibnewton) \ No newline at end of file +[leibnewton](https://github.com/leibnewton) +[Grin](https://github.com/xyyangkun) +[xbpeng121](https://github.com/xbpeng121) +[lvchenyun](https://github.com/lvchenyun) +[Fummowo](https://github.com/Fummowo) +[Jovial Young ](https://github.com/JHYoung1034) +[yujitai](https://github.com/yujitai) +[KisChang](https://github.com/kisChang) +[zjx94](https://github.com/zjx94) +[LeiZhi.Mai ](https://github.com/blueskiner) +[JiaHao](https://github.com/nashiracn) diff --git a/Android/app/src/main/cpp/native-lib.cpp b/Android/app/src/main/cpp/native-lib.cpp index 9eb0ca17..48ab0f63 100644 --- a/Android/app/src/main/cpp/native-lib.cpp +++ b/Android/app/src/main/cpp/native-lib.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/CMakeLists.txt b/CMakeLists.txt index 39c6c517..b9dbfa64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,11 +24,13 @@ cmake_minimum_required(VERSION 3.1.3) # 加载自定义模块 +# Load custom modules list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") project(ZLMediaKit LANGUAGES C CXX) # 使能 C++11 +# Enable C++11 set(CMAKE_CXX_STANDARD 11) option(ENABLE_API "Enable C API SDK" ON) @@ -42,7 +44,6 @@ option(ENABLE_JEMALLOC_STATIC "Enable static linking to the jemalloc library" OF option(ENABLE_JEMALLOC_DUMP "Enable jemalloc to dump malloc statistics" OFF) option(ENABLE_MEM_DEBUG "Enable Memory Debug" OFF) option(ENABLE_MP4 "Enable MP4" ON) -option(ENABLE_HLS_FMP4 "Enable HLS-FMP4" ON) option(ENABLE_MSVC_MT "Enable MSVC Mt/Mtd lib" ON) option(ENABLE_MYSQL "Enable MySQL" OFF) option(ENABLE_OPENSSL "Enable OpenSSL" ON) @@ -58,8 +59,11 @@ option(ENABLE_X264 "Enable x264" OFF) option(ENABLE_WEPOLL "Enable wepoll" ON) option(DISABLE_REPORT "Disable report to report.zlmediakit.com" off) option(USE_SOLUTION_FOLDERS "Enable solution dir supported" ON) - ############################################################################## +# 设置socket默认缓冲区大小为256k.如果设置为0则不设置socket的默认缓冲区大小,使用系统内核默认值(设置为0仅对linux有效) +# Set the default buffer size of the socket to 256k. If set to 0, the default buffer size of the socket will not be set, +# and the system kernel default value will be used (setting to 0 is only valid for linux) +set(SOCKET_DEFAULT_BUF_SIZE 262144 CACHE STRING "Default buffer size for socket" FORCE) if("${CMAKE_BUILD_TYPE}" STREQUAL "") set(CMAKE_BUILD_TYPE "Debug") @@ -68,12 +72,14 @@ endif() message(STATUS "编译类型: ${CMAKE_BUILD_TYPE}") # 方便排查编译问题, 需要 FORCE CACHE, 否则需要命令行设置才生效 +# To facilitate the troubleshooting of compilation problems, you need to FORCE CACHE, otherwise you need to set it on the command line to take effect set(CMAKE_VERBOSE_MAKEFILE ON CACHE INTERNAL "" FORCE) # TODO: include 当前目录会导致 server 编译出错, 待排除 set(CMAKE_INCLUDE_CURRENT_DIR OFF) # 安装路径 +# Install path if(NOT CMAKE_INSTALL_PREFIX) if(UNIX) set(INSTALL_PATH_LIB lib${LIB_SUFFIX}) @@ -81,6 +87,7 @@ if(NOT CMAKE_INSTALL_PREFIX) set(INSTALL_PATH_RUNTIME bin) elseif(WIN32) # Windows 下安装到了用户主目录下? + # Install to the user's home directory under Windows? set(INSTALL_PATH_LIB $ENV{HOME}/${CMAKE_PROJECT_NAME}/lib) set(INSTALL_PATH_INCLUDE $ENV{HOME}/${CMAKE_PROJECT_NAME}/include) else() @@ -95,11 +102,14 @@ endif() string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME_LOWER) # 设置输出目录, 包括 bin, lib 以及其他文件 # Windows 也不再区分 32/64 +# Set the output directory, including bin, lib and other files +# Windows no longer distinguishes 32/64 set(OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/release/${SYSTEM_NAME_LOWER}/${CMAKE_BUILD_TYPE}) set(LIBRARY_OUTPUT_PATH ${OUTPUT_DIR}) set(EXECUTABLE_OUTPUT_PATH ${OUTPUT_DIR}) # 添加 git 版本信息 +# Add git version information set(COMMIT_HASH "Git_Unkown_commit") set(COMMIT_TIME "Git_Unkown_time") set(BRANCH_NAME "Git_Unkown_branch") @@ -140,6 +150,7 @@ message(STATUS "Git version is ${BRANCH_NAME} ${COMMIT_HASH}/${COMMIT_TIME} ${BU ############################################################################## # 方便修改全局变量 +# Convenient to modify global variables function(update_cached name value) set("${name}" "${value}" CACHE INTERNAL "*** Internal ***" FORCE) endfunction() @@ -202,6 +213,7 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") endif() # mediakit 以及各个 runtime 依赖 +# mediakit and various runtime dependencies update_cached(MK_LINK_LIBRARIES "") update_cached(MK_COMPILE_DEFINITIONS ENABLE_VERSION) @@ -226,9 +238,11 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") endif() # 多个模块依赖 ffmpeg 相关库, 统一查找 +# Multiple modules depend on ffmpeg related libraries, unified search if(ENABLE_FFMPEG) find_package(PkgConfig QUIET) # 查找 ffmpeg/libutil 是否安装 + # find ffmpeg/libutil installed if(PKG_CONFIG_FOUND) pkg_check_modules(AVUTIL QUIET IMPORTED_TARGET libavutil) if(AVUTIL_FOUND) @@ -238,6 +252,7 @@ if(ENABLE_FFMPEG) endif() # 查找 ffmpeg/libavcodec 是否安装 + # find ffmpeg/libavcodec installed if(PKG_CONFIG_FOUND) pkg_check_modules(AVCODEC QUIET IMPORTED_TARGET libavcodec) if(AVCODEC_FOUND) @@ -247,6 +262,7 @@ if(ENABLE_FFMPEG) endif() # 查找 ffmpeg/libswscale 是否安装 + # find ffmpeg/libswscale installed if(PKG_CONFIG_FOUND) pkg_check_modules(SWSCALE QUIET IMPORTED_TARGET libswscale) if(SWSCALE_FOUND) @@ -256,6 +272,7 @@ if(ENABLE_FFMPEG) endif() # 查找 ffmpeg/libswresample 是否安装 + # find ffmpeg/libswresample installed if(PKG_CONFIG_FOUND) pkg_check_modules(SWRESAMPLE QUIET IMPORTED_TARGET libswresample) if(SWRESAMPLE_FOUND) @@ -265,6 +282,7 @@ if(ENABLE_FFMPEG) endif() # 查找 ffmpeg/libutil 是否安装 + # find ffmpeg/libutil installed if(NOT AVUTIL_FOUND) find_package(AVUTIL QUIET) if(AVUTIL_FOUND) @@ -275,6 +293,7 @@ if(ENABLE_FFMPEG) endif () # 查找 ffmpeg/libavcodec 是否安装 + # find ffmpeg/libavcodec installed if(NOT AVCODEC_FOUND) find_package(AVCODEC QUIET) if(AVCODEC_FOUND) @@ -285,6 +304,7 @@ if(ENABLE_FFMPEG) endif() # 查找 ffmpeg/libswscale 是否安装 + # find ffmpeg/libswscale installed if(NOT SWSCALE_FOUND) find_package(SWSCALE QUIET) if(SWSCALE_FOUND) @@ -295,6 +315,7 @@ if(ENABLE_FFMPEG) endif() # 查找 ffmpeg/libswresample 是否安装 + # find ffmpeg/libswresample installed if(NOT SWRESAMPLE_FOUND) find_package(SWRESAMPLE QUIET) if(SWRESAMPLE_FOUND) @@ -309,7 +330,7 @@ if(ENABLE_FFMPEG) update_cached_list(MK_LINK_LIBRARIES ${CMAKE_DL_LIBS}) else() set(ENABLE_FFMPEG OFF) - message(WARNING "ffmpeg 相关功能未找到") + message(WARNING "ffmpeg related functions not found") endif() endif() @@ -317,7 +338,7 @@ if(ENABLE_MEM_DEBUG) update_cached_list(MK_LINK_LIBRARIES "-Wl,-wrap,free;-Wl,-wrap,malloc;-Wl,-wrap,realloc;-Wl,-wrap,calloc") update_cached_list(MK_COMPILE_DEFINITIONS ENABLE_MEM_DEBUG) - message(STATUS "已启用内存调试功能") + message(STATUS "Memory debugging enabled") endif() if(ENABLE_ASAN) @@ -327,10 +348,11 @@ if(ENABLE_ASAN) # > In order to use AddressSanitizer you will need to # > compile and link your program using clang with the -fsanitize=address switch. update_cached_list(MK_LINK_LIBRARIES "-fsanitize=address") - message(STATUS "已启用 Address Sanitize") + message(STATUS "Address Sanitize enabled") endif() -# TODO: 下载静态编译 jemalloc 后静态编译链接? +# 下载jemalloc后静态编译 +# Static compilation after downloading jemalloc set(DEP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdpart/external-${CMAKE_SYSTEM_NAME}) if(ENABLE_JEMALLOC_STATIC) if(NOT EXISTS ${DEP_ROOT_DIR}) @@ -345,10 +367,12 @@ if(ENABLE_JEMALLOC_STATIC) include_directories(SYSTEM ${DEP_ROOT_DIR}/${JEMALLOC_NAME}/include/jemalloc) link_directories(${DEP_ROOT_DIR}/${JEMALLOC_NAME}/lib) # 用于影响后续查找过程 + # Used to affect subsequent lookup process set(JEMALLOC_ROOT_DIR "${DEP_ROOT_DIR}/${JEMALLOC_NAME}") endif() # 默认链接 jemalloc 库避免内存碎片 +# Link the jemalloc library by default to avoid memory fragmentation find_package(JEMALLOC QUIET) if(JEMALLOC_FOUND) message(STATUS "found library: ${JEMALLOC_LIBRARIES}") @@ -363,6 +387,7 @@ if(JEMALLOC_FOUND) endif() # 查找 openssl 是否安装 +# find openssl installed find_package(OpenSSL QUIET) if(OPENSSL_FOUND AND ENABLE_OPENSSL) message(STATUS "found library: ${OPENSSL_LIBRARIES}, ENABLE_OPENSSL defined") @@ -379,6 +404,7 @@ else() endif() # 查找 mysql 是否安装 +# find mysql installed find_package(MYSQL QUIET) if(MYSQL_FOUND AND ENABLE_MYSQL) message(STATUS "found library: ${MYSQL_LIBRARIES}, ENABLE_MYSQL defined") @@ -391,6 +417,7 @@ if(MYSQL_FOUND AND ENABLE_MYSQL) endif() # 查找 x264 是否安装 +# find x264 installed find_package(X264 QUIET) if(X264_FOUND AND ENABLE_X264) message(STATUS "found library: ${X264_LIBRARIES}, ENABLE_X264 defined") @@ -401,6 +428,7 @@ if(X264_FOUND AND ENABLE_X264) endif() # 查找 faac 是否安装 +# find faac installed find_package(FAAC QUIET) if(FAAC_FOUND AND ENABLE_FAAC) message(STATUS "found library:${FAAC_LIBRARIES}, ENABLE_FAAC defined") @@ -449,6 +477,8 @@ add_subdirectory(3rdpart) add_subdirectory(src) +add_subdirectory(ext-codec) + if(ENABLE_SRT) add_subdirectory(srt) endif() @@ -468,26 +498,31 @@ if(ENABLE_PLAYER AND ENABLE_FFMPEG) endif() #MediaServer主程序 +#MediaServer main program if(ENABLE_SERVER) add_subdirectory(server) endif() # Android 会 add_subdirectory 并依赖该变量 +# Android will add_subdirectory and depend on this variable if(ENABLE_SERVER_LIB AND NOT CMAKE_PARENT_LIST_FILE STREQUAL CMAKE_CURRENT_LIST_FILE) set(MK_LINK_LIBRARIES ${MK_LINK_LIBRARIES} PARENT_SCOPE) endif() # IOS 不编译可执行程序 +# IOS does not compile executable programs if(IOS) return() endif() #cpp测试demo程序 +#cpp test demo program if (ENABLE_TESTS) add_subdirectory(tests) endif () # 拷贝www文件夹、配置文件、默认证书 +# Copy www folder, configuration file, default certificate file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/www" DESTINATION ${EXECUTABLE_OUTPUT_PATH}) file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/conf/config.ini" DESTINATION ${EXECUTABLE_OUTPUT_PATH}) file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/default.pem" DESTINATION ${EXECUTABLE_OUTPUT_PATH}) diff --git a/LICENSE b/LICENSE index cdbc206a..1be14df3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. +Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,3 +19,11 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +---------------------------------------------------------------------------------------- + +补充协议: + +本项目采用类MIT协议,用户在履行MIT协议义务的同时,应当同时遵循保留ZLMediaKit软件版权信息的义务。 +用户不得去除ZLMediaKit提供的各种服务中包括但不限于 "title"、"Server"、"User-Agent" 等字段中 "ZLMediaKit" 的信息。 +否则本项目主要权利人(项目发起人、主要作者)保留声索起诉的权利。 diff --git a/README.md b/README.md index a32a5d9f..56f29476 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ - 极致体验,[独家特性](https://github.com/ZLMediaKit/ZLMediaKit/wiki/ZLMediakit%E7%8B%AC%E5%AE%B6%E7%89%B9%E6%80%A7%E4%BB%8B%E7%BB%8D) - [谁在使用zlmediakit?](https://github.com/ZLMediaKit/ZLMediaKit/issues/511) - 全面支持ipv6网络 +- 支持多轨道模式(一个流中多个视频/音频) ## 项目定位 @@ -76,16 +77,19 @@ - 通过cookie追踪技术,可以模拟HLS播放为长连接,可以实现HLS按需拉流、播放统计等业务 - 支持HLS播发器,支持拉流HLS转rtsp/rtmp/mp4 - 支持H264/H265/AAC/G711/OPUS编码 + - 支持多轨道模式 - TS - 支持http[s]-ts直播 - 支持ws[s]-ts直播 - 支持H264/H265/AAC/G711/OPUS编码 + - 支持多轨道模式 - fMP4 - 支持http[s]-fmp4直播 - 支持ws[s]-fmp4直播 - 支持H264/H265/AAC/G711/OPUS/MJPEG编码 + - 支持多轨道模式 - HTTP[S]与WebSocket - 服务器支持`目录索引生成`,`文件下载`,`表单提交请求` @@ -104,11 +108,13 @@ - 支持es/ps rtp转推 - 支持GB28181主动拉流模式 - 支持双向语音对讲 + - 支持多轨道模式 - MP4点播与录制 - 支持录制为FLV/HLS/MP4 - RTSP/RTMP/HTTP-FLV/WS-FLV支持MP4文件点播,支持seek - 支持H264/H265/AAC/G711/OPUS编码 + - 支持多轨道模式 - WebRTC - 支持WebRTC推流,支持转其他协议 @@ -188,6 +194,8 @@ bash build_docker_images.sh - [AKStreamNVR](https://github.com/langmansh/AKStreamNVR) 前后端分离web项目,支持webrtc播放 - SDK + - [spring-boot-starter](https://github.com/lunasaw/zlm-spring-boot-starter) 本项目hook和rest接口starter + - [java sdk](https://github.com/lidaofu-hub/j_zlm_sdk) 本项目c sdk完整java包装库 - [c# sdk](https://github.com/malegend/ZLMediaKit.Autogen) 本项目c sdk完整c#包装库 - [metaRTC](https://github.com/metartc/metaRTC) 全国产纯c webrtc sdk @@ -334,6 +342,16 @@ bash build_docker_images.sh [ArmstrongCN](https://github.com/ArmstrongCN) [leibnewton](https://github.com/leibnewton) [1002victor](https://github.com/1002victor) +[Grin](https://github.com/xyyangkun) +[xbpeng121](https://github.com/xbpeng121) +[lvchenyun](https://github.com/lvchenyun) +[Fummowo](https://github.com/Fummowo) +[Jovial Young ](https://github.com/JHYoung1034) +[yujitai](https://github.com/yujitai) +[KisChang](https://github.com/kisChang) +[zjx94](https://github.com/zjx94) +[LeiZhi.Mai ](https://github.com/blueskiner) +[JiaHao](https://github.com/nashiracn) 同时感谢JetBrains对开源项目的支持,本项目使用CLion开发与调试: diff --git a/README_en.md b/README_en.md index 0c8c6437..d4fd9afb 100644 --- a/README_en.md +++ b/README_en.md @@ -157,7 +157,7 @@ It is recommended to compile on Ubuntu or macOS. Compiling on Windows is cumbers - **You must use Git to clone the complete code. Do not download the source code by downloading the ZIP package. Otherwise, the submodule code will not be downloaded by default. You can do it like this:** ``` -git clone https://github.com/xia-chu/ZLMediaKit.git +git clone https://github.com/ZLMediaKit/ZLMediaKit.git cd ZLMediaKit git submodule update --init ``` @@ -357,6 +357,8 @@ bash build_docker_images.sh - [Hikvision ehome server implemented in Go](https://github.com/tsingeye/FreeEhome) - Client + - [Http Api and hook in zlm-spring-boot-starter](https://github.com/lunasaw/zlm-spring-boot-starter) + - [Complete java wrapper library for c sdk](https://github.com/lidaofu-hub/j_zlm_sdk) - [Complete C# wrapper library for c sdk](https://github.com/malegend/ZLMediaKit.Autogen) - [Push client implemented based on C SDK](https://github.com/hctym1995/ZLM_ApiDemo) - [Http API and Hook in C#](https://github.com/chengxiaosheng/ZLMediaKit.HttpApi) @@ -498,6 +500,16 @@ Thanks to all those who have supported this project in various ways, including b [ArmstrongCN](https://github.com/ArmstrongCN) [leibnewton](https://github.com/leibnewton) [1002victor](https://github.com/1002victor) +[Grin](https://github.com/xyyangkun) +[xbpeng121](https://github.com/xbpeng121) +[lvchenyun](https://github.com/lvchenyun) +[Fummowo](https://github.com/Fummowo) +[Jovial Young ](https://github.com/JHYoung1034) +[yujitai](https://github.com/yujitai) +[KisChang](https://github.com/kisChang) +[zjx94](https://github.com/zjx94) +[LeiZhi.Mai ](https://github.com/blueskiner) +[JiaHao](https://github.com/nashiracn) Also thank to JetBrains for their support for open source project, we developed and debugged zlmediakit with CLion: diff --git a/api/include/mk_common.h b/api/include/mk_common.h index 33a3790e..90b4c8a6 100755 --- a/api/include/mk_common.h +++ b/api/include/mk_common.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_events.h b/api/include/mk_events.h index 0db68a5f..7e18263b 100644 --- a/api/include/mk_events.h +++ b/api/include/mk_events.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_events_objects.h b/api/include/mk_events_objects.h index 624970f3..ad039b5c 100644 --- a/api/include/mk_events_objects.h +++ b/api/include/mk_events_objects.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_frame.h b/api/include/mk_frame.h index 62498096..56309d4f 100644 --- a/api/include/mk_frame.h +++ b/api/include/mk_frame.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_h264_splitter.h b/api/include/mk_h264_splitter.h index 24db3599..1249db6e 100644 --- a/api/include/mk_h264_splitter.h +++ b/api/include/mk_h264_splitter.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_httpclient.h b/api/include/mk_httpclient.h index c76d4ce0..e07101de 100755 --- a/api/include/mk_httpclient.h +++ b/api/include/mk_httpclient.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_media.h b/api/include/mk_media.h index dfefda1b..e7277462 100755 --- a/api/include/mk_media.h +++ b/api/include/mk_media.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_mediakit.h b/api/include/mk_mediakit.h index 42c1ddc0..b7682195 100755 --- a/api/include/mk_mediakit.h +++ b/api/include/mk_mediakit.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_player.h b/api/include/mk_player.h index 5ab0eea5..3aa9b836 100755 --- a/api/include/mk_player.h +++ b/api/include/mk_player.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_proxyplayer.h b/api/include/mk_proxyplayer.h index bb7afac0..e851aa8c 100644 --- a/api/include/mk_proxyplayer.h +++ b/api/include/mk_proxyplayer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_pusher.h b/api/include/mk_pusher.h index adb905e5..fd5c63d5 100644 --- a/api/include/mk_pusher.h +++ b/api/include/mk_pusher.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_recorder.h b/api/include/mk_recorder.h index a23e50f4..96f35065 100644 --- a/api/include/mk_recorder.h +++ b/api/include/mk_recorder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_rtp_server.h b/api/include/mk_rtp_server.h index add2104d..60cdb43d 100644 --- a/api/include/mk_rtp_server.h +++ b/api/include/mk_rtp_server.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_tcp.h b/api/include/mk_tcp.h index 4ab19da1..7157b47e 100644 --- a/api/include/mk_tcp.h +++ b/api/include/mk_tcp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_thread.h b/api/include/mk_thread.h index 79994154..b03c9502 100644 --- a/api/include/mk_thread.h +++ b/api/include/mk_thread.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_track.h b/api/include/mk_track.h index b7a01b7f..430c3cfc 100644 --- a/api/include/mk_track.h +++ b/api/include/mk_track.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_transcode.h b/api/include/mk_transcode.h index 1c4bd0ce..80866e69 100644 --- a/api/include/mk_transcode.h +++ b/api/include/mk_transcode.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/include/mk_util.h b/api/include/mk_util.h index bd5b29ce..32f9da7a 100644 --- a/api/include/mk_util.h +++ b/api/include/mk_util.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_common.cpp b/api/source/mk_common.cpp index a45068ce..1f94cf28 100644 --- a/api/source/mk_common.cpp +++ b/api/source/mk_common.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -280,7 +280,6 @@ API_EXPORT uint16_t API_CALL mk_rtc_server_start(uint16_t port) { class WebRtcArgsUrl : public mediakit::WebRtcArgs { public: WebRtcArgsUrl(std::string url) { _url = std::move(url); } - ~WebRtcArgsUrl() = default; toolkit::variant operator[](const std::string &key) const override { if (key == "url") { @@ -305,7 +304,8 @@ API_EXPORT void API_CALL mk_webrtc_get_answer_sdp2(void *user_data, on_user_data auto session = std::make_shared(Socket::createSocket()); std::string offer_str = offer; std::shared_ptr ptr(user_data, user_data_free ? user_data_free : [](void *) {}); - WebRtcPluginManager::Instance().getAnswerSdp(*session, type, WebRtcArgsUrl(url), + auto args = std::make_shared(url); + WebRtcPluginManager::Instance().getAnswerSdp(*session, type, *args, [offer_str, session, ptr, cb](const WebRtcInterface &exchanger) mutable { try { auto sdp_answer = exchangeSdp(exchanger, offer_str); diff --git a/api/source/mk_events.cpp b/api/source/mk_events.cpp index 6e81ccc5..ae454e60 100644 --- a/api/source/mk_events.cpp +++ b/api/source/mk_events.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_events_objects.cpp b/api/source/mk_events_objects.cpp index 5dacafb4..1d74e0e1 100644 --- a/api/source/mk_events_objects.cpp +++ b/api/source/mk_events_objects.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_frame.cpp b/api/source/mk_frame.cpp index 7a7cdb85..adf03e1c 100644 --- a/api/source/mk_frame.cpp +++ b/api/source/mk_frame.cpp @@ -1,115 +1,70 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "mk_frame.h" -#include "mk_track.h" -#include "Extension/Frame.h" -#include "Extension/H264.h" -#include "Extension/H265.h" -#include "Extension/AAC.h" #include "Record/MPEG.h" +#include "Extension/Factory.h" using namespace mediakit; extern "C" { -#define XX(name, type, value, str, mpeg_id) API_EXPORT const int MK##name = value; +#define XX(name, type, value, str, mpeg_id, mp4_id) API_EXPORT const int MK##name = value; CODEC_MAP(XX) #undef XX } -class FrameFromPtrForC : public FrameFromPtr { +namespace { +class BufferFromPtr : public toolkit::Buffer { public: - using Ptr = std::shared_ptr; - - template - FrameFromPtrForC(bool cache_able, uint32_t flags, on_mk_frame_data_release cb, std::shared_ptr user_data, ARGS &&...args) : FrameFromPtr( - std::forward(args)...) { - _flags = flags; + BufferFromPtr(char *ptr, size_t size, on_mk_frame_data_release cb, std::shared_ptr user_data) { + _ptr = ptr; + _size = size; _cb = cb; _user_data = std::move(user_data); - _cache_able = cache_able; } - ~FrameFromPtrForC() override { - if (_cb) { - _cb(_user_data.get(), _ptr); - } + ~BufferFromPtr() override { + _cb(_user_data.get(), _ptr); } - bool cacheAble() const override { - return _cache_able; - } - - bool keyFrame() const override { - return _flags & MK_FRAME_FLAG_IS_KEY; - } - - bool configFrame() const override { - return _flags & MK_FRAME_FLAG_IS_CONFIG; - } - - //默认返回false - bool dropAble() const override { - return _flags & MK_FRAME_FLAG_DROP_ABLE; - } - - //默认返回true - bool decodeAble() const override { - return !(_flags & MK_FRAME_FLAG_NOT_DECODE_ABLE); - } + char *data() const override { return _ptr; } + size_t size() const override { return _size; } private: - uint32_t _flags; + char *_ptr; + size_t _size; on_mk_frame_data_release _cb; std::shared_ptr _user_data; - bool _cache_able; }; +}; // namespace -static mk_frame mk_frame_create_complex(int codec_id, uint64_t dts, uint64_t pts, uint32_t frame_flags, size_t prefix_size, - char *data, size_t size, on_mk_frame_data_release cb, std::shared_ptr user_data) { - switch (codec_id) { - case CodecH264: - return (mk_frame)new Frame::Ptr(new H264FrameHelper( - cb, frame_flags, cb, std::move(user_data), (CodecId)codec_id, data, size, dts, pts, prefix_size)); - case CodecH265: - return (mk_frame)new Frame::Ptr(new H265FrameHelper( - cb, frame_flags, cb, std::move(user_data), (CodecId)codec_id, data, size, dts, pts, prefix_size)); - default: - return (mk_frame)new Frame::Ptr(new FrameFromPtrForC( - cb, frame_flags, cb, std::move(user_data), (CodecId)codec_id, data, size, dts, pts, prefix_size)); +static mk_frame mk_frame_create_complex(int codec_id, uint64_t dts, uint64_t pts, const char *data, size_t size, + on_mk_frame_data_release cb, std::shared_ptr user_data) { + if (!cb) { + // no cacheable + return (mk_frame) new Frame::Ptr(Factory::getFrameFromPtr((CodecId)codec_id, data, size, dts, pts)); } + // cacheable + auto buffer = std::make_shared((char *)data, size, cb, std::move(user_data)); + return (mk_frame) new Frame::Ptr(Factory::getFrameFromBuffer((CodecId)codec_id, std::move(buffer), dts, pts)); } API_EXPORT mk_frame API_CALL mk_frame_create(int codec_id, uint64_t dts, uint64_t pts, const char *data, size_t size, - on_mk_frame_data_release cb, void *user_data) { + on_mk_frame_data_release cb, void *user_data) { return mk_frame_create2(codec_id, dts, pts, data, size, cb, user_data, nullptr); } + API_EXPORT mk_frame API_CALL mk_frame_create2(int codec_id, uint64_t dts, uint64_t pts, const char *data, size_t size, - on_mk_frame_data_release cb, void *user_data, on_user_data_free user_data_free) { + on_mk_frame_data_release cb, void *user_data, on_user_data_free user_data_free) { std::shared_ptr ptr(user_data, user_data_free ? user_data_free : [](void *) {}); - switch (codec_id) { - case CodecH264: - case CodecH265: - return mk_frame_create_complex(codec_id, dts, pts, 0, prefixSize(data, size), (char *)data, size, cb, std::move(ptr)); - - case CodecAAC: { - int prefix = 0; - if ((((uint8_t *) data)[0] == 0xFF && (((uint8_t *) data)[1] & 0xF0) == 0xF0) && size > ADTS_HEADER_LEN) { - prefix = ADTS_HEADER_LEN; - } - return mk_frame_create_complex(codec_id, dts, pts, 0, prefix, (char *)data, size, cb, std::move(ptr)); - } - - default: - return mk_frame_create_complex(codec_id, dts, pts, 0, 0, (char *)data, size, cb, std::move(ptr)); - } + return mk_frame_create_complex(codec_id, dts, pts, data, size, cb, std::move(ptr)); } API_EXPORT void API_CALL mk_frame_unref(mk_frame frame) { diff --git a/api/source/mk_h264_splitter.cpp b/api/source/mk_h264_splitter.cpp index 5f146dba..a6c412f4 100644 --- a/api/source/mk_h264_splitter.cpp +++ b/api/source/mk_h264_splitter.cpp @@ -1,17 +1,16 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "mk_h264_splitter.h" #include "Http/HttpRequestSplitter.h" -#include "Extension/H264.h" -#include "Extension/H265.h" +#include "Extension/Factory.h" using namespace mediakit; @@ -71,9 +70,9 @@ const char *H264Splitter::onSearchPacketTail(const char *data, size_t len) { auto last_frame_len = next_frame - last_frame; Frame::Ptr frame; if (_h265) { - frame = std::make_shared((char *) last_frame, last_frame_len, 0, 0, prefixSize(last_frame, last_frame_len)); + frame = Factory::getFrameFromPtr(CodecH265, (char *)last_frame, last_frame_len, 0, 0); } else { - frame = std::make_shared((char *) last_frame, last_frame_len, 0, 0, prefixSize(last_frame, last_frame_len)); + frame = Factory::getFrameFromPtr(CodecH264, (char *)last_frame, last_frame_len, 0, 0); } if (frame->decodeAble()) { _search_pos = 0; diff --git a/api/source/mk_httpclient.cpp b/api/source/mk_httpclient.cpp index 43de7a33..fb7c774b 100755 --- a/api/source/mk_httpclient.cpp +++ b/api/source/mk_httpclient.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_media.cpp b/api/source/mk_media.cpp index 3e1d33e0..fda298af 100755 --- a/api/source/mk_media.cpp +++ b/api/source/mk_media.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_player.cpp b/api/source/mk_player.cpp index 82adc411..42dc956b 100755 --- a/api/source/mk_player.cpp +++ b/api/source/mk_player.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,7 +11,6 @@ #include "mk_player.h" #include "Util/logger.h" #include "Player/MediaPlayer.h" -#include "Extension/H264.h" using namespace std; using namespace toolkit; @@ -24,7 +23,6 @@ public: MediaPlayerForC(){ _player = std::make_shared(); } - ~MediaPlayerForC() = default; MediaPlayer *operator->(){ return _player.get(); diff --git a/api/source/mk_proxyplayer.cpp b/api/source/mk_proxyplayer.cpp index 01171e77..653a9868 100644 --- a/api/source/mk_proxyplayer.cpp +++ b/api/source/mk_proxyplayer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_pusher.cpp b/api/source/mk_pusher.cpp index 48956f7d..9292081e 100644 --- a/api/source/mk_pusher.cpp +++ b/api/source/mk_pusher.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_recorder.cpp b/api/source/mk_recorder.cpp index f99d7130..adc2a70a 100644 --- a/api/source/mk_recorder.cpp +++ b/api/source/mk_recorder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_rtp_server.cpp b/api/source/mk_rtp_server.cpp index 3f5f2a09..6d2228d2 100644 --- a/api/source/mk_rtp_server.cpp +++ b/api/source/mk_rtp_server.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_tcp.cpp b/api/source/mk_tcp.cpp index d155cac8..166be169 100644 --- a/api/source/mk_tcp.cpp +++ b/api/source/mk_tcp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_tcp_private.h b/api/source/mk_tcp_private.h index e569ca16..1dd0f74d 100644 --- a/api/source/mk_tcp_private.h +++ b/api/source/mk_tcp_private.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -33,9 +33,8 @@ private: class SessionForC : public toolkit::Session { public: - SessionForC(const toolkit::Socket::Ptr &pSock) ; - ~SessionForC() override = default; - void onRecv(const toolkit::Buffer::Ptr &buffer) override ; + SessionForC(const toolkit::Socket::Ptr &pSock); + void onRecv(const toolkit::Buffer::Ptr &buffer) override; void onError(const toolkit::SockException &err) override; void onManager() override; std::shared_ptr _user_data; diff --git a/api/source/mk_thread.cpp b/api/source/mk_thread.cpp index 29775b43..26379c8b 100644 --- a/api/source/mk_thread.cpp +++ b/api/source/mk_thread.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -80,8 +80,6 @@ public: _user_data = std::move(user_data); } - ~TimerForC() = default; - uint64_t operator()(){ lock_guard lck(_mxt); if(!_cb){ @@ -135,8 +133,6 @@ API_EXPORT void API_CALL mk_timer_release(mk_timer ctx){ class WorkThreadPoolForC : public TaskExecutorGetterImp { public: - ~WorkThreadPoolForC() override = default; - WorkThreadPoolForC(const char *name, size_t n_thread, int priority) { //最低优先级 addPoller(name, n_thread, (ThreadPool::Priority) priority, false); diff --git a/api/source/mk_track.cpp b/api/source/mk_track.cpp index d20b01d0..c409ef22 100644 --- a/api/source/mk_track.cpp +++ b/api/source/mk_track.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -27,8 +27,6 @@ public: } } - ~VideoTrackForC() override = default; - int getVideoHeight() const override { return _args.video.height; } @@ -45,16 +43,16 @@ public: return _codec_id; } - bool ready() override { + bool ready() const override { return true; } - Track::Ptr clone() override { - auto track_in = std::shared_ptr(shared_from_this()); + Track::Ptr clone() const override { + auto track_in = std::shared_ptr(const_cast(this)->shared_from_this()); return Factory::getTrackByAbstractTrack(track_in); } - Sdp::Ptr getSdp() override { + Sdp::Ptr getSdp(uint8_t) const override { return nullptr; } @@ -65,17 +63,15 @@ private: class AudioTrackForC : public AudioTrackImp, public std::enable_shared_from_this { public: - ~AudioTrackForC() override = default; - AudioTrackForC(int codec_id, codec_args *args) : AudioTrackImp((CodecId) codec_id, args->audio.sample_rate, args->audio.channels, 16) {} - Track::Ptr clone() override { - auto track_in = std::shared_ptr(shared_from_this()); + Track::Ptr clone() const override { + auto track_in = std::shared_ptr(const_cast(this)->shared_from_this()); return Factory::getTrackByAbstractTrack(track_in); } - Sdp::Ptr getSdp() override { + Sdp::Ptr getSdp(uint8_t payload_type) const override { return nullptr; } }; diff --git a/api/source/mk_transcode.cpp b/api/source/mk_transcode.cpp index 6d118325..ad24b552 100644 --- a/api/source/mk_transcode.cpp +++ b/api/source/mk_transcode.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/source/mk_util.cpp b/api/source/mk_util.cpp index 5c5d3197..66d0d3b2 100644 --- a/api/source/mk_util.cpp +++ b/api/source/mk_util.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/tests/h264_media_server.c b/api/tests/h264_media_server.c index f10c9b6b..427afeaf 100644 --- a/api/tests/h264_media_server.c +++ b/api/tests/h264_media_server.c @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/tests/httpclient.c b/api/tests/httpclient.c index 053dde8e..1e6c39ec 100644 --- a/api/tests/httpclient.c +++ b/api/tests/httpclient.c @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/tests/player_opencv.c b/api/tests/player_opencv.c index 1d18faa3..042fd6ef 100644 --- a/api/tests/player_opencv.c +++ b/api/tests/player_opencv.c @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/tests/pusher.c b/api/tests/pusher.c index 2014fd09..03b2b971 100644 --- a/api/tests/pusher.c +++ b/api/tests/pusher.c @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/tests/server.c b/api/tests/server.c index d331519c..4f76fe60 100644 --- a/api/tests/server.c +++ b/api/tests/server.c @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/api/tests/websocket.c b/api/tests/websocket.c index 54335046..aadee586 100644 --- a/api/tests/websocket.c +++ b/api/tests/websocket.c @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/conf/config.ini b/conf/config.ini index dc343b32..d1d8246c 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -15,6 +15,8 @@ secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc snapRoot=./www/snap/ #默认截图图片,在启动FFmpeg截图后但是截图还未生成时,可以返回默认的预设图片 defaultSnap=./www/logo.png +#downloadFile http接口可访问文件的根目录,支持多个目录,不同目录通过分号(;)分隔 +downloadRoot=./www [ffmpeg] #FFmpeg可执行程序路径,支持相对路径/绝对路径 @@ -50,6 +52,10 @@ auto_close=0 #此参数不应大于播放器超时时间;单位毫秒 continue_push_ms=15000 +#平滑发送定时器间隔,单位毫秒,置0则关闭;开启后影响cpu性能同时增加内存 +#该配置开启后可以解决一些流发送不平滑导致zlmediakit转发也不平滑的问题 +paced_sender_ms=0 + #是否开启转换为hls(mpegts) enable_hls=1 #是否开启转换为hls(fmp4) @@ -140,48 +146,50 @@ deleteDelaySec=10 #0为不保留,不起作用 #1为保留,则不删除hls文件,如果开启此功能,注意磁盘大小,或者定期手动清理hls文件 segKeep=0 +#如果设置为1,则第一个切片长度强制设置为1个GOP。当GOP小于segDur,可以提高首屏速度 +fastRegister=0 [hook] #是否启用hook事件,启用后,推拉流都将进行鉴权 enable=0 #播放器或推流器使用流量事件,置空则关闭 -on_flow_report=https://127.0.0.1/index/hook/on_flow_report +on_flow_report= #访问http文件鉴权事件,置空则关闭鉴权 -on_http_access=https://127.0.0.1/index/hook/on_http_access +on_http_access= #播放鉴权事件,置空则关闭鉴权 -on_play=https://127.0.0.1/index/hook/on_play +on_play= #推流鉴权事件,置空则关闭鉴权 -on_publish=https://127.0.0.1/index/hook/on_publish +on_publish= #录制mp4切片完成事件 -on_record_mp4=https://127.0.0.1/index/hook/on_record_mp4 +on_record_mp4= # 录制 hls ts(或fmp4) 切片完成事件 -on_record_ts=https://127.0.0.1/index/hook/on_record_ts +on_record_ts= #rtsp播放鉴权事件,此事件中比对rtsp的用户名密码 -on_rtsp_auth=https://127.0.0.1/index/hook/on_rtsp_auth +on_rtsp_auth= #rtsp播放是否开启专属鉴权事件,置空则关闭rtsp鉴权。rtsp播放鉴权还支持url方式鉴权 #建议开发者统一采用url参数方式鉴权,rtsp用户名密码鉴权一般在设备上用的比较多 #开启rtsp专属鉴权后,将不再触发on_play鉴权事件 -on_rtsp_realm=https://127.0.0.1/index/hook/on_rtsp_realm +on_rtsp_realm= #远程telnet调试鉴权事件 -on_shell_login=https://127.0.0.1/index/hook/on_shell_login +on_shell_login= #直播流注册或注销事件 -on_stream_changed=https://127.0.0.1/index/hook/on_stream_changed +on_stream_changed= #过滤on_stream_changed hook的协议类型,可以选择只监听某些感兴趣的协议;置空则不过滤协议 stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4 #无人观看流事件,通过该事件,可以选择是否关闭无人观看的流。配合general.streamNoneReaderDelayMS选项一起使用 -on_stream_none_reader=https://127.0.0.1/index/hook/on_stream_none_reader +on_stream_none_reader= #播放时,未找到流事件,通过配合hook.on_stream_none_reader事件可以完成按需拉流 -on_stream_not_found=https://127.0.0.1/index/hook/on_stream_not_found +on_stream_not_found= #服务器启动报告,可以用于服务器的崩溃重启事件监听 -on_server_started=https://127.0.0.1/index/hook/on_server_started +on_server_started= #服务器退出报告,当服务器正常退出时触发 -on_server_exited=https://127.0.0.1/index/hook/on_server_exited +on_server_exited= #server保活上报 -on_server_keepalive=https://127.0.0.1/index/hook/on_server_keepalive +on_server_keepalive= #发送rtp(startSendRtp)被动关闭时回调 -on_send_rtp_stopped=https://127.0.0.1/index/hook/on_send_rtp_stopped +on_send_rtp_stopped= #rtp server 超时未收到数据 -on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout +on_rtp_server_timeout= #hook api最大等待回复时间,单位秒 timeoutSec=10 @@ -278,6 +286,10 @@ keepAliveSecond=15 port=1935 #rtmps服务器监听地址 sslport=0 +# rtmp是否直接代理模式 +directProxy=1 +#h265 rtmp打包采用增强型rtmp标准还是国内拓展标准 +enhanced=1 [rtp] #音频mtu大小,该参数限制rtp最大字节数,推荐不要超过1400 @@ -339,6 +351,11 @@ preferredCodecA=PCMU,PCMA,opus,mpeg4-generic #以下范例为所有支持的视频codec preferredCodecV=H264,H265,AV1,VP9,VP8 +#webrtc比特率设置 +start_bitrate=0 +max_bitrate=0 +min_bitrate=0 + [srt] #srt播放推流、播放超时时间,单位秒 timeoutSec=5 diff --git a/conf/readme.md b/conf/readme.md new file mode 100644 index 00000000..78256609 --- /dev/null +++ b/conf/readme.md @@ -0,0 +1,24 @@ +## 配置文件影响性能的参数 + +### 1、protocol.enable_xxx +控制转协议开关,关闭某些协议节省cpu和内存。 + +### 2、protocol.xxx_demand +控制按需转协议,开启转协议且按需转协议时,无人观看时节省cpu和内存,但是第一个播放器无法秒开,影响体验 + +### 3、protocol.paced_sender_ms +平滑发送定时器频率,用于解决数据源发送不平滑导致转发不平滑播放器卡顿问题,开启后定时器根据数据时间戳驱动数据发送,提高用户体验。 +但是增加cpu和内存使用。定时器间隔越小,cpu占用越高,但是平滑度越好,建议设置30~100ms。此功能结合protocol.modify_stamp为2(抑制时间戳跳跃)最佳。 + +### 4、general.mergeWriteMS +开启合并写,减少发送数据时系统调用次数以及线程间数据共享频率,大大提高转发性能,但是牺牲播放延时和发送平滑度。 + +### 5、rtp_proxy.gop_cache +开启startSendRtp级联接口的gop缓存功能,用于国标级联秒开。该选项不影响zlmediakit对外提供直播服务的秒开。 +开启该选项后增加内存使用,对cpu影响较小,如果不调用startSendRtp接口,建议关闭。 + +### 6、hls.fileBufSize +调整该配置可以提高hls协议写磁盘io性能。 + +### 7、record.fileBufSize +调整该配置可以提高mp4录制写磁盘io性能。 diff --git a/docker/centos7/Dockerfile.runtime b/docker/centos7/Dockerfile.runtime index c7d9f990..8ec20d18 100644 --- a/docker/centos7/Dockerfile.runtime +++ b/docker/centos7/Dockerfile.runtime @@ -94,7 +94,7 @@ RUN cd /opt \ && make install RUN cd /opt \ - && git clone --depth 1 https://github.com/xia-chu/ZLMediaKit.git \ + && git clone --depth 1 https://github.com/ZLMediaKit/ZLMediaKit.git \ && cd ZLMediaKit \ && git submodule update --init \ && mkdir -p build release/linux/Release/ \ @@ -112,7 +112,7 @@ RUN mkdir -p /opt/build/opt/zlm/ /opt/build/usr/local/bin/ /opt/build/usr/bin/ && /usr/bin/cp -ip /usr/bin/which ./usr/bin/ FROM centos:${Version} -LABEL maintainer="chengxiaosheng " project-url="https://github.com/xia-chu/ZLMediaKit" description="一个基于C++11的高性能运营级流媒体服务框架" +LABEL maintainer="chengxiaosheng " project-url="https://github.com/ZLMediaKit/ZLMediaKit" description="一个基于C++11的高性能运营级流媒体服务框架" EXPOSE 9000/tcp \ 1935/tcp \ diff --git a/docker/ubuntu16.04/Dockerfile.devel b/docker/ubuntu16.04/Dockerfile.devel index 65ff0958..5cbb3483 100644 --- a/docker/ubuntu16.04/Dockerfile.devel +++ b/docker/ubuntu16.04/Dockerfile.devel @@ -32,7 +32,7 @@ RUN apt-get update && \ RUN mkdir -p /opt/media WORKDIR /opt/media -RUN git clone --depth=1 https://github.com/xia-chu/ZLMediaKit && \ +RUN git clone --depth=1 https://github.com/ZLMediaKit/ZLMediaKit && \ cd ZLMediaKit && git submodule update --init --recursive && \ mkdir -p build release/linux/Release/ diff --git a/docker/ubuntu16.04/Dockerfile.runtime b/docker/ubuntu16.04/Dockerfile.runtime index bc869e92..c5d13691 100644 --- a/docker/ubuntu16.04/Dockerfile.runtime +++ b/docker/ubuntu16.04/Dockerfile.runtime @@ -31,7 +31,7 @@ RUN apt-get update && \ RUN mkdir -p /opt/media WORKDIR /opt/media -RUN git clone --depth=1 https://github.com/xia-chu/ZLMediaKit && \ +RUN git clone --depth=1 https://github.com/ZLMediaKit/ZLMediaKit && \ cd ZLMediaKit && git submodule update --init --recursive && \ mkdir -p build release/linux/Release/ diff --git a/docker/ubuntu18.04/Dockerfile.devel b/docker/ubuntu18.04/Dockerfile.devel index 0a61d86c..6829e6f8 100644 --- a/docker/ubuntu18.04/Dockerfile.devel +++ b/docker/ubuntu18.04/Dockerfile.devel @@ -33,7 +33,7 @@ RUN apt-get update && \ RUN mkdir -p /opt/media WORKDIR /opt/media -RUN git clone --depth=1 https://github.com/xia-chu/ZLMediaKit && \ +RUN git clone --depth=1 https://github.com/ZLMediaKit/ZLMediaKit && \ cd ZLMediaKit && git submodule update --init --recursive && \ mkdir -p build release/linux/Release/ diff --git a/docker/ubuntu18.04/Dockerfile.runtime b/docker/ubuntu18.04/Dockerfile.runtime index 0a1bae65..a9e7a535 100644 --- a/docker/ubuntu18.04/Dockerfile.runtime +++ b/docker/ubuntu18.04/Dockerfile.runtime @@ -31,7 +31,7 @@ RUN apt-get update && \ RUN mkdir -p /opt/media WORKDIR /opt/media -RUN git clone --depth=1 https://github.com/xia-chu/ZLMediaKit && \ +RUN git clone --depth=1 https://github.com/ZLMediaKit/ZLMediaKit && \ cd ZLMediaKit && git submodule update --init --recursive && \ mkdir -p build release/linux/Release/ diff --git a/src/Extension/AAC.cpp b/ext-codec/AAC.cpp similarity index 67% rename from src/Extension/AAC.cpp rename to ext-codec/AAC.cpp index 27f18359..62c443da 100644 --- a/src/Extension/AAC.cpp +++ b/ext-codec/AAC.cpp @@ -1,14 +1,18 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "AAC.h" +#include "AACRtp.h" +#include "AACRtmp.h" +#include "Common/Parser.h" +#include "Extension/Factory.h" #ifdef ENABLE_MP4 #include "mpeg4-aac.h" #endif @@ -205,39 +209,31 @@ public: /** * 构造函数 * @param aac_cfg aac两个字节的配置描述 + * @param payload_type rtp payload type * @param sample_rate 音频采样率 - * @param payload_type rtp payload type 默认98 + * @param channels 通道数 * @param bitrate 比特率 */ - AACSdp(const string &aac_cfg, - int sample_rate, - int channels, - int bitrate = 128, - int payload_type = 98) : Sdp(sample_rate,payload_type){ + AACSdp(const string &aac_cfg, int payload_type, int sample_rate, int channels, int bitrate) + : Sdp(sample_rate, payload_type) { _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << sample_rate << "/" << channels << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecAAC) << "/" << sample_rate << "/" << channels << "\r\n"; string configStr; - char buf[4] = {0}; - for(auto &ch : aac_cfg){ + char buf[4] = { 0 }; + for (auto &ch : aac_cfg) { snprintf(buf, sizeof(buf), "%02X", (uint8_t)ch); configStr.append(buf); } _printer << "a=fmtp:" << payload_type << " streamtype=5;profile-level-id=1;mode=AAC-hbr;" << "sizelength=13;indexlength=3;indexdeltalength=3;config=" << configStr << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; } - string getSdp() const override { - return _printer; - } + string getSdp() const override { return _printer; } - CodecId getCodecId() const override { - return CodecAAC; - } private: _StrPrinter _printer; }; @@ -249,18 +245,14 @@ AACTrack::AACTrack(const string &aac_cfg) { throw std::invalid_argument("adts配置必须最少2个字节"); } _cfg = aac_cfg; - onReady(); -} - -const string &AACTrack::getConfig() const { - return _cfg; + update(); } CodecId AACTrack::getCodecId() const { return CodecAAC; } -bool AACTrack::ready() { +bool AACTrack::ready() const { return !_cfg.empty(); } @@ -276,9 +268,25 @@ int AACTrack::getAudioChannel() const { return _channel; } +static Frame::Ptr addADTSHeader(const Frame::Ptr &frame_in, const std::string &aac_config) { + auto frame = FrameImp::create(); + frame->_codec_id = CodecAAC; + // 生成adts头 + char adts_header[32] = { 0 }; + auto size = dumpAacConfig(aac_config, frame_in->size(), (uint8_t *)adts_header, sizeof(adts_header)); + CHECK(size > 0, "Invalid adts config"); + frame->_prefix_size = size; + frame->_dts = frame_in->dts(); + frame->_buffer.assign(adts_header, size); + frame->_buffer.append(frame_in->data(), frame_in->size()); + frame->setIndex(frame_in->getIndex()); + return frame; +} + bool AACTrack::inputFrame(const Frame::Ptr &frame) { if (!frame->prefixSize()) { - return inputFrame_l(frame); + CHECK(ready()); + return inputFrame_l(addADTSHeader(frame, _cfg)); } bool ret = false; @@ -289,70 +297,137 @@ bool AACTrack::inputFrame(const Frame::Ptr &frame) { auto ptr = frame->data(); auto end = frame->data() + frame->size(); while (ptr < end) { - auto frame_len = getAacFrameLength((uint8_t *) ptr, end - ptr); + auto frame_len = getAacFrameLength((uint8_t *)ptr, end - ptr); if (frame_len < ADTS_HEADER_LEN) { break; } if (frame_len == (int)frame->size()) { return inputFrame_l(frame); } - auto sub_frame = std::make_shared >(frame, (char *) ptr, frame_len, ADTS_HEADER_LEN,dts,pts); + auto sub_frame = std::make_shared>(frame, (char *)ptr, frame_len, dts, pts, ADTS_HEADER_LEN); ptr += frame_len; if (ptr > end) { WarnL << "invalid aac length in adts header: " << frame_len << ", remain data size: " << end - (ptr - frame_len); break; } - sub_frame->setCodecId(CodecAAC); if (inputFrame_l(sub_frame)) { ret = true; } - dts += 1024*1000/getAudioSampleRate(); - pts += 1024*1000/getAudioSampleRate(); + dts += 1024 * 1000 / getAudioSampleRate(); + pts += 1024 * 1000 / getAudioSampleRate(); } return ret; } bool AACTrack::inputFrame_l(const Frame::Ptr &frame) { - if (_cfg.empty()) { - //未获取到aac_cfg信息 - if (frame->prefixSize()) { - //根据7个字节的adts头生成aac config - _cfg = makeAacConfig((uint8_t *) (frame->data()), frame->prefixSize()); - onReady(); - } else { - WarnL << "无法获取adts头!"; - } + if (_cfg.empty() && frame->prefixSize()) { + // 未获取到aac_cfg信息,根据7个字节的adts头生成aac config + _cfg = makeAacConfig((uint8_t *)(frame->data()), frame->prefixSize()); + update(); } if (frame->size() > frame->prefixSize()) { - //除adts头外,有实际负载 + // 除adts头外,有实际负载 return AudioTrack::inputFrame(frame); } return false; } +toolkit::Buffer::Ptr AACTrack::getExtraData() const { + CHECK(ready()); + return std::make_shared(_cfg); +} + +void AACTrack::setExtraData(const uint8_t *data, size_t size) { + CHECK(size >= 2); + _cfg.assign((char *)data, size); + update(); +} + bool AACTrack::update() { return parseAacConfig(_cfg, _sampleRate, _channel); } -void AACTrack::onReady() { - if (!parseAacConfig(_cfg, _sampleRate, _channel)) { - _cfg.clear(); - } +Track::Ptr AACTrack::clone() const { + return std::make_shared(*this); } -Track::Ptr AACTrack::clone() { - return std::make_shared::type>(*this); -} - -Sdp::Ptr AACTrack::getSdp() { - if(!ready()){ +Sdp::Ptr AACTrack::getSdp(uint8_t payload_type) const { + if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } - update(); - return std::make_shared(getConfig(), getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); + return std::make_shared(getExtraData()->toString(), payload_type, getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); } -}//namespace mediakit \ No newline at end of file +namespace { + +CodecId getCodec() { + return CodecAAC; +} + +Track::Ptr getTrackByCodecId(int sample_rate, int channels, int sample_bit) { + return std::make_shared(); +} + +Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track) { + string aac_cfg_str = findSubString(track->_fmtp.data(), "config=", ";"); + if (aac_cfg_str.empty()) { + aac_cfg_str = findSubString(track->_fmtp.data(), "config=", nullptr); + } + if (aac_cfg_str.empty()) { + // 如果sdp中获取不到aac config信息,那么在rtp也无法获取,那么忽略该Track + return nullptr; + } + string aac_cfg; + for (size_t i = 0; i < aac_cfg_str.size() / 2; ++i) { + unsigned int cfg; + sscanf(aac_cfg_str.substr(i * 2, 2).data(), "%02X", &cfg); + cfg &= 0x00FF; + aac_cfg.push_back((char)cfg); + } + return std::make_shared(aac_cfg); +} + +RtpCodec::Ptr getRtpEncoderByCodecId(uint8_t pt) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpDecoderByCodecId() { + return std::make_shared(); +} + +RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +size_t aacPrefixSize(const char *data, size_t bytes) { + uint8_t *ptr = (uint8_t *)data; + size_t prefix = 0; + if (!(bytes > ADTS_HEADER_LEN && ptr[0] == 0xFF && (ptr[1] & 0xF0) == 0xF0)) { + return 0; + } + return ADTS_HEADER_LEN; +} + +Frame::Ptr getFrameFromPtr(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return std::make_shared(CodecAAC, (char *)data, bytes, dts, pts, aacPrefixSize(data, bytes)); +} + +} // namespace + +CodecPlugin aac_plugin = { getCodec, + getTrackByCodecId, + getTrackBySdp, + getRtpEncoderByCodecId, + getRtpDecoderByCodecId, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtr }; + +} // namespace mediakit \ No newline at end of file diff --git a/ext-codec/AAC.h b/ext-codec/AAC.h new file mode 100644 index 00000000..0b6eeec1 --- /dev/null +++ b/ext-codec/AAC.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef ZLMEDIAKIT_AAC_H +#define ZLMEDIAKIT_AAC_H + +#include "Extension/Frame.h" +#include "Extension/Track.h" +#define ADTS_HEADER_LEN 7 + +namespace mediakit{ + +/** + * aac音频通道 + */ +class AACTrack : public AudioTrack { +public: + using Ptr = std::shared_ptr; + + AACTrack() = default; + + /** + * 通过aac extra data 构造对象 + */ + AACTrack(const std::string &aac_cfg); + + bool ready() const override; + CodecId getCodecId() const override; + int getAudioChannel() const override; + int getAudioSampleRate() const override; + int getAudioSampleBit() const override; + bool inputFrame(const Frame::Ptr &frame) override; + toolkit::Buffer::Ptr getExtraData() const override; + void setExtraData(const uint8_t *data, size_t size) override; + bool update() override; + +private: + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; + bool inputFrame_l(const Frame::Ptr &frame); + +private: + std::string _cfg; + int _channel = 0; + int _sampleRate = 0; + int _sampleBit = 16; +}; + +}//namespace mediakit +#endif //ZLMEDIAKIT_AAC_H \ No newline at end of file diff --git a/ext-codec/AACRtmp.cpp b/ext-codec/AACRtmp.cpp new file mode 100644 index 00000000..e20db4df --- /dev/null +++ b/ext-codec/AACRtmp.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#include "AACRtmp.h" +#include "Rtmp/Rtmp.h" + +using namespace std; +using namespace toolkit; + +namespace mediakit { + +void AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { + CHECK(pkt->size() > 2); + if (pkt->isConfigFrame()) { + getTrack()->setExtraData((uint8_t *)pkt->data() + 2, pkt->size() - 2); + return; + } + RtmpCodec::inputFrame(std::make_shared(CodecAAC, pkt->buffer.data() + 2, pkt->buffer.size() - 2, pkt->time_stamp)); +} + +///////////////////////////////////////////////////////////////////////////////////// + +bool AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) { + auto pkt = RtmpPacket::create(); + // header + pkt->buffer.push_back(_audio_flv_flags); + pkt->buffer.push_back((uint8_t)RtmpAACPacketType::aac_raw); + // aac data + pkt->buffer.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); + pkt->body_size = pkt->buffer.size(); + pkt->chunk_id = CHUNK_AUDIO; + pkt->stream_index = STREAM_MEDIA; + pkt->time_stamp = frame->dts(); + pkt->type_id = MSG_AUDIO; + RtmpCodec::inputRtmp(pkt); + return true; +} + +void AACRtmpEncoder::makeConfigPacket() { + _audio_flv_flags = getAudioRtmpFlags(getTrack()); + auto pkt = RtmpPacket::create(); + // header + pkt->buffer.push_back(_audio_flv_flags); + pkt->buffer.push_back((uint8_t)RtmpAACPacketType::aac_config_header); + + // aac config + auto extra_data = getTrack()->getExtraData(); + CHECK(extra_data); + pkt->buffer.append(extra_data->data(), extra_data->size()); + + pkt->body_size = pkt->buffer.size(); + pkt->chunk_id = CHUNK_AUDIO; + pkt->stream_index = STREAM_MEDIA; + pkt->time_stamp = 0; + pkt->type_id = MSG_AUDIO; + RtmpCodec::inputRtmp(pkt); +} + +}//namespace mediakit \ No newline at end of file diff --git a/src/Extension/AACRtmp.h b/ext-codec/AACRtmp.h similarity index 58% rename from src/Extension/AACRtmp.h rename to ext-codec/AACRtmp.h index fd34c495..55c3eb34 100644 --- a/src/Extension/AACRtmp.h +++ b/ext-codec/AACRtmp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,43 +11,31 @@ #ifndef ZLMEDIAKIT_AACRTMPCODEC_H #define ZLMEDIAKIT_AACRTMPCODEC_H +#include "AAC.h" #include "Rtmp/RtmpCodec.h" #include "Extension/Track.h" -#include "Extension/AAC.h" -namespace mediakit{ +namespace mediakit { /** * aac Rtmp转adts类 */ -class AACRtmpDecoder : public RtmpCodec{ +class AACRtmpDecoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - AACRtmpDecoder() {} - ~AACRtmpDecoder() {} + AACRtmpDecoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入Rtmp并解码 * @param rtmp Rtmp数据包 */ void inputRtmp(const RtmpPacket::Ptr &rtmp) override; - - CodecId getCodecId() const override{ - return CodecAAC; - } - -private: - void onGetAAC(const char *data, size_t len, uint32_t stamp); - -private: - std::string _aac_cfg; }; - /** * aac adts转Rtmp类 */ -class AACRtmpEncoder : public AACRtmpDecoder{ +class AACRtmpEncoder : public RtmpCodec { public: using Ptr = std::shared_ptr; @@ -57,8 +45,7 @@ public: * 那么inputFrame时可以不输入adts头 * @param track */ - AACRtmpEncoder(const Track::Ptr &track); - ~AACRtmpEncoder() {} + AACRtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入aac 数据,可以不带adts头 @@ -72,12 +59,7 @@ public: void makeConfigPacket() override; private: - void makeAudioConfigPkt(); - -private: - uint8_t _audio_flv_flags; - AACTrack::Ptr _track; - std::string _aac_cfg; + uint8_t _audio_flv_flags {0}; }; }//namespace mediakit diff --git a/src/Extension/AACRtp.cpp b/ext-codec/AACRtp.cpp similarity index 55% rename from src/Extension/AACRtp.cpp rename to ext-codec/AACRtp.cpp index b5c5ab39..0d9228bc 100644 --- a/src/Extension/AACRtp.cpp +++ b/ext-codec/AACRtp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -12,63 +12,36 @@ namespace mediakit{ -AACRtpEncoder::AACRtpEncoder(uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PayloadType, - uint8_t ui8Interleaved) : - RtpInfo(ui32Ssrc, - ui32MtuSize, - ui32SampleRate, - ui8PayloadType, - ui8Interleaved){ -} - bool AACRtpEncoder::inputFrame(const Frame::Ptr &frame) { - auto stamp = frame->dts(); - auto data = frame->data() + frame->prefixSize(); - auto len = frame->size() - frame->prefixSize(); - auto ptr = (char *) data; - auto remain_size = len; - auto max_size = getMaxSize() - 4; + auto ptr = (char *)frame->data() + frame->prefixSize(); + auto size = frame->size() - frame->prefixSize(); + auto remain_size = size; + auto max_size = getRtpInfo().getMaxSize() - 4; while (remain_size > 0) { if (remain_size <= max_size) { - _section_buf[0] = 0; - _section_buf[1] = 16; - _section_buf[2] = (len >> 5) & 0xFF; - _section_buf[3] = ((len & 0x1F) << 3) & 0xFF; - memcpy(_section_buf + 4, ptr, remain_size); - makeAACRtp(_section_buf, remain_size + 4, true, stamp); + outputRtp(ptr, remain_size, size, true, frame->dts()); break; } - _section_buf[0] = 0; - _section_buf[1] = 16; - _section_buf[2] = ((len) >> 5) & 0xFF; - _section_buf[3] = ((len & 0x1F) << 3) & 0xFF; - memcpy(_section_buf + 4, ptr, max_size); - makeAACRtp(_section_buf, max_size + 4, false, stamp); + outputRtp(ptr, max_size, size, false, frame->dts()); ptr += max_size; remain_size -= max_size; } - return len > 0; + return true; } -void AACRtpEncoder::makeAACRtp(const void *data, size_t len, bool mark, uint64_t stamp) { - RtpCodec::inputRtp(makeRtp(getTrackType(), data, len, mark, stamp), false); +void AACRtpEncoder::outputRtp(const char *data, size_t len, size_t total_len, bool mark, uint64_t stamp) { + auto rtp = getRtpInfo().makeRtp(TrackAudio, nullptr, len + 4, mark, stamp); + auto payload = rtp->data() + RtpPacket::kRtpTcpHeaderSize + RtpPacket::kRtpHeaderSize; + payload[0] = 0; + payload[1] = 16; + payload[2] = ((total_len) >> 5) & 0xFF; + payload[3] = ((total_len & 0x1F) << 3) & 0xFF; + memcpy(payload + 4, data, len); + RtpCodec::inputRtp(std::move(rtp), false); } ///////////////////////////////////////////////////////////////////////////////////// -AACRtpDecoder::AACRtpDecoder(const Track::Ptr &track) { - auto aacTrack = std::dynamic_pointer_cast(track); - if (!aacTrack || !aacTrack->ready()) { - WarnL << "该aac track无效!"; - } else { - _aac_cfg = aacTrack->getConfig(); - } - obtainFrame(); -} - AACRtpDecoder::AACRtpDecoder() { obtainFrame(); } @@ -145,17 +118,8 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) { void AACRtpDecoder::flushData() { auto ptr = reinterpret_cast(_frame->data()); if ((ptr[0] == 0xFF && (ptr[1] & 0xF0) == 0xF0) && _frame->size() > ADTS_HEADER_LEN) { - //adts头打入了rtp包,不符合规范,兼容EasyPusher的bug + // adts头打入了rtp包,不符合规范,兼容EasyPusher的bug _frame->_prefix_size = ADTS_HEADER_LEN; - } else { - //没有adts头则插入adts头 - char adts_header[128] = {0}; - auto size = dumpAacConfig(_aac_cfg, _frame->_buffer.size(), (uint8_t *) adts_header, sizeof(adts_header)); - if (size > 0) { - //插入adts头 - _frame->_buffer.insert(0, adts_header, size); - _frame->_prefix_size = size; - } } RtpCodec::inputFrame(_frame); obtainFrame(); diff --git a/ext-codec/AACRtp.h b/ext-codec/AACRtp.h new file mode 100644 index 00000000..f4559c27 --- /dev/null +++ b/ext-codec/AACRtp.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef ZLMEDIAKIT_AACRTPCODEC_H +#define ZLMEDIAKIT_AACRTPCODEC_H + +#include "AAC.h" +#include "Rtsp/RtpCodec.h" + +namespace mediakit { +/** + * aac rtp转adts类 + */ +class AACRtpDecoder : public RtpCodec { +public: + using Ptr = std::shared_ptr; + + AACRtpDecoder(); + + /** + * 输入rtp并解码 + * @param rtp rtp数据包 + * @param key_pos 此参数内部强制转换为false,请忽略之 + */ + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override; + +private: + void obtainFrame(); + void flushData(); + +private: + uint64_t _last_dts = 0; + FrameImp::Ptr _frame; +}; + + +/** + * aac adts转rtp类 + */ +class AACRtpEncoder : public RtpCodec { +public: + using Ptr = std::shared_ptr; + + /** + * 输入aac 数据,必须带dats头 + * @param frame 带dats头的aac数据 + */ + bool inputFrame(const Frame::Ptr &frame) override; + +private: + void outputRtp(const char *data, size_t len, size_t total_len, bool mark, uint64_t stamp); + +}; + +}//namespace mediakit + +#endif //ZLMEDIAKIT_AACRTPCODEC_H diff --git a/ext-codec/CMakeLists.txt b/ext-codec/CMakeLists.txt new file mode 100644 index 00000000..23190fb8 --- /dev/null +++ b/ext-codec/CMakeLists.txt @@ -0,0 +1,48 @@ +# MIT License +# +# Copyright (c) 2016-2022 The ZLMediaKit project authors. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +set(COMPILE_DEFINITIONS) +set(INCLUDE_DIRECTORIES) + +file(GLOB EXT_SRC_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) + +add_library(ext-codec STATIC ${EXT_SRC_LIST}) +add_library(ZLMediaKit::ext-codec ALIAS ext-codec) + +target_compile_options(ext-codec PRIVATE ${COMPILE_OPTIONS_DEFAULT}) +target_compile_definitions(ext-codec PUBLIC ${COMPILE_DEFINITIONS}) + +target_link_libraries(ext-codec PRIVATE ZLMediaKit::MediaKit ZLMediaKit::ToolKit ${LINK_LIBRARIES}) + +target_include_directories(ext-codec + PRIVATE + "$" + PUBLIC + "$" + ${INCLUDE_DIRECTORIES}) + +update_cached_list(MK_LINK_LIBRARIES ZLMediaKit::ext-codec ${LINK_LIBRARIES}) diff --git a/ext-codec/G711.cpp b/ext-codec/G711.cpp new file mode 100644 index 00000000..e8c05df5 --- /dev/null +++ b/ext-codec/G711.cpp @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#include "G711.h" +#include "G711Rtp.h" +#include "Extension/Factory.h" +#include "Extension/CommonRtp.h" +#include "Extension/CommonRtmp.h" + +using namespace std; +using namespace toolkit; + +namespace mediakit { + +/** + * G711类型SDP + */ +class G711Sdp : public Sdp { +public: + /** + * G711采样率固定为8000 + * @param codecId G711A G711U + * @param payload_type rtp payload type + * @param sample_rate 音频采样率 + * @param channels 通道数 + * @param bitrate 比特率 + */ + G711Sdp(CodecId codecId, int payload_type, int sample_rate, int channels, int bitrate) + : Sdp(sample_rate, payload_type) { + _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; + if (bitrate) { + _printer << "b=AS:" << bitrate << "\r\n"; + } + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(codecId) << "/" << sample_rate << "/" << channels << "\r\n"; + } + + string getSdp() const override { + return _printer; + } + +private: + _StrPrinter _printer; +}; + +Track::Ptr G711Track::clone() const { + return std::make_shared(*this); +} + +Sdp::Ptr G711Track::getSdp(uint8_t payload_type) const { + if (!ready()) { + WarnL << getCodecName() << " Track未准备好"; + return nullptr; + } + + const auto codec = getCodecId(); + const auto sample_rate = getAudioSampleRate(); + const auto audio_channel = getAudioChannel(); + const auto bitrate = getBitRate() >> 10; + if (sample_rate == 8000 && audio_channel == 1) { + // https://datatracker.ietf.org/doc/html/rfc3551#section-6 + payload_type = (codec == CodecG711U) ? Rtsp::PT_PCMU : Rtsp::PT_PCMA; + } + + return std::make_shared(codec, payload_type, sample_rate, audio_channel, bitrate); +} + + +namespace { + +CodecId getCodecA() { + return CodecG711A; +} + +CodecId getCodecU() { + return CodecG711U; +} + +Track::Ptr getTrackByCodecId_l(CodecId codec, int sample_rate, int channels, int sample_bit) { + return (sample_rate && channels && sample_bit) ? std::make_shared(codec, sample_rate, channels, sample_bit) : nullptr; +} + +Track::Ptr getTrackByCodecIdA(int sample_rate, int channels, int sample_bit) { + return getTrackByCodecId_l(CodecG711A, sample_rate, channels, sample_bit); +} + +Track::Ptr getTrackByCodecIdU(int sample_rate, int channels, int sample_bit) { + return getTrackByCodecId_l(CodecG711U, sample_rate, channels, sample_bit); +} + +Track::Ptr getTrackBySdp_l(CodecId codec, const SdpTrack::Ptr &track) { + return std::make_shared(codec, track->_samplerate, track->_channel, 16); +} + +Track::Ptr getTrackBySdpA(const SdpTrack::Ptr &track) { + return getTrackBySdp_l(CodecG711A, track); +} + +Track::Ptr getTrackBySdpU(const SdpTrack::Ptr &track) { + return getTrackBySdp_l(CodecG711U, track); +} + +RtpCodec::Ptr getRtpEncoderByCodecId_l(CodecId codec, uint8_t pt) { + if (pt == Rtsp::PT_PCMA || pt == Rtsp::PT_PCMU) { + return std::make_shared(codec, 1); + } + return std::make_shared(); +} + +RtpCodec::Ptr getRtpEncoderByCodecIdA(uint8_t pt) { + return getRtpEncoderByCodecId_l(CodecG711A, pt); +} + +RtpCodec::Ptr getRtpEncoderByCodecIdU(uint8_t pt) { + return getRtpEncoderByCodecId_l(CodecG711U, pt); +} + +RtpCodec::Ptr getRtpDecoderByCodecId_l(CodecId codec) { + return std::make_shared(codec); +} + +RtpCodec::Ptr getRtpDecoderByCodecIdA() { + return getRtpDecoderByCodecId_l(CodecG711A); +} + +RtpCodec::Ptr getRtpDecoderByCodecIdU() { + return getRtpDecoderByCodecId_l(CodecG711U); +} + +RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track) { + auto audio_track = dynamic_pointer_cast(track); + if (audio_track->getAudioSampleRate() != 8000 || audio_track->getAudioChannel() != 1 || audio_track->getAudioSampleBit() != 16) { + //rtmp对g711只支持8000/1/16规格,但是ZLMediaKit可以解析其他规格的G711 + WarnL << "RTMP only support G711 with 8000/1/16, now is" + << audio_track->getAudioSampleRate() << "/" + << audio_track->getAudioChannel() << "/" + << audio_track->getAudioSampleBit() + << ", ignored it"; + return nullptr; + } + return std::make_shared(track); +} + +RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +Frame::Ptr getFrameFromPtr_l(CodecId codec, const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return std::make_shared(codec, (char *)data, bytes, dts, pts); +} + +Frame::Ptr getFrameFromPtrA(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return getFrameFromPtr_l(CodecG711A, (char *)data, bytes, dts, pts); +} + +Frame::Ptr getFrameFromPtrU(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return getFrameFromPtr_l(CodecG711U, (char *)data, bytes, dts, pts); +} + +} // namespace + +CodecPlugin g711a_plugin = { getCodecA, + getTrackByCodecIdA, + getTrackBySdpA, + getRtpEncoderByCodecIdA, + getRtpDecoderByCodecIdA, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtrA }; + +CodecPlugin g711u_plugin = { getCodecU, + getTrackByCodecIdU, + getTrackBySdpU, + getRtpEncoderByCodecIdU, + getRtpDecoderByCodecIdU, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtrU }; + +}//namespace mediakit + + diff --git a/src/Extension/G711.h b/ext-codec/G711.h similarity index 57% rename from src/Extension/G711.h rename to ext-codec/G711.h index 550acbc4..be510553 100644 --- a/src/Extension/G711.h +++ b/ext-codec/G711.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,8 +11,8 @@ #ifndef ZLMEDIAKIT_G711_H #define ZLMEDIAKIT_G711_H -#include "Frame.h" -#include "Track.h" +#include "Extension/Frame.h" +#include "Extension/Track.h" namespace mediakit{ @@ -25,8 +25,8 @@ public: G711Track(CodecId codecId, int sample_rate, int channels, int sample_bit) : AudioTrackImp(codecId, 8000, 1, 16) {} private: - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; }; }//namespace mediakit diff --git a/src/Extension/G711Rtp.cpp b/ext-codec/G711Rtp.cpp similarity index 79% rename from src/Extension/G711Rtp.cpp rename to ext-codec/G711Rtp.cpp index ce74eda1..2760f8a6 100644 --- a/src/Extension/G711Rtp.cpp +++ b/ext-codec/G711Rtp.cpp @@ -2,11 +2,7 @@ namespace mediakit { -G711RtpEncoder::G711RtpEncoder( - CodecId codec, uint32_t ssrc, uint32_t mtu_size, uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved, - uint32_t channels) - : CommonRtpDecoder(codec) - , RtpInfo(ssrc, mtu_size, sample_rate, payload_type, interleaved) { +G711RtpEncoder::G711RtpEncoder(CodecId codec, uint32_t channels){ _cache_frame = FrameImp::create(); _cache_frame->_codec_id = codec; _channels = channels; @@ -40,7 +36,7 @@ bool G711RtpEncoder::inputFrame(const Frame::Ptr &frame) { } n++; stamp += 20; - RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, rtp_size, mark, stamp), false); + RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackAudio, ptr, rtp_size, mark, stamp), false); ptr += rtp_size; remain_size -= rtp_size; } diff --git a/ext-codec/G711Rtp.h b/ext-codec/G711Rtp.h new file mode 100644 index 00000000..2d709e53 --- /dev/null +++ b/ext-codec/G711Rtp.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef ZLMEDIAKIT_G711RTP_H +#define ZLMEDIAKIT_G711RTP_H + +#include "Rtsp/RtpCodec.h" +#include "Extension/Frame.h" +#include "Extension/CommonRtp.h" + +namespace mediakit { + +/** + * G711 rtp编码类 + */ +class G711RtpEncoder : public RtpCodec { +public: + using Ptr = std::shared_ptr; + + /** + * 构造函数 + * @param codec 编码类型 + * @param channels 通道数 + */ + G711RtpEncoder(CodecId codec, uint32_t channels); + + /** + * 输入帧数据并编码成rtp + */ + bool inputFrame(const Frame::Ptr &frame) override; + +private: + uint32_t _channels = 1; + FrameImp::Ptr _cache_frame; +}; + +}//namespace mediakit +#endif //ZLMEDIAKIT_G711RTP_H diff --git a/src/Extension/H264.cpp b/ext-codec/H264.cpp similarity index 59% rename from src/Extension/H264.cpp rename to ext-codec/H264.cpp index eda6b188..59471775 100644 --- a/src/Extension/H264.cpp +++ b/ext-codec/H264.cpp @@ -1,18 +1,26 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "H264.h" +#include "H264Rtmp.h" +#include "H264Rtp.h" #include "SPSParser.h" #include "Util/logger.h" #include "Util/base64.h" +#include "Common/Parser.h" #include "Common/config.h" +#include "Extension/Factory.h" + +#ifdef ENABLE_MP4 +#include "mpeg4-avc.h" +#endif using namespace std; using namespace toolkit; @@ -109,24 +117,7 @@ size_t prefixSize(const char *ptr, size_t len) { H264Track::H264Track(const string &sps, const string &pps, int sps_prefix_len, int pps_prefix_len) { _sps = sps.substr(sps_prefix_len); _pps = pps.substr(pps_prefix_len); - onReady(); -} - -H264Track::H264Track(const Frame::Ptr &sps, const Frame::Ptr &pps) { - if (sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264) { - throw std::invalid_argument("必须输入H264类型的帧"); - } - _sps = string(sps->data() + sps->prefixSize(), sps->size() - sps->prefixSize()); - _pps = string(pps->data() + pps->prefixSize(), pps->size() - pps->prefixSize()); - onReady(); -} - -const string &H264Track::getSps() const { - return _sps; -} - -const string &H264Track::getPps() const { - return _pps; + update(); } CodecId H264Track::getCodecId() const { @@ -145,7 +136,7 @@ float H264Track::getVideoFps() const { return _fps; } -bool H264Track::ready() { +bool H264Track::ready() const { return !_sps.empty() && !_pps.empty(); } @@ -168,19 +159,87 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) { return ret; } +toolkit::Buffer::Ptr H264Track::getExtraData() const { + CHECK(ready()); + +#ifdef ENABLE_MP4 + struct mpeg4_avc_t avc; + memset(&avc, 0, sizeof(avc)); + string sps_pps = string("\x00\x00\x00\x01", 4) + _sps + string("\x00\x00\x00\x01", 4) + _pps; + h264_annexbtomp4(&avc, sps_pps.data(), (int)sps_pps.size(), NULL, 0, NULL, NULL); + + std::string extra_data; + extra_data.resize(1024); + auto extra_data_size = mpeg4_avc_decoder_configuration_record_save(&avc, (uint8_t *)extra_data.data(), extra_data.size()); + if (extra_data_size == -1) { + WarnL << "生成H264 extra_data 失败"; + return nullptr; + } + extra_data.resize(extra_data_size); + return std::make_shared(std::move(extra_data)); +#else + std::string extra_data; + // AVCDecoderConfigurationRecord start + extra_data.push_back(1); // version + extra_data.push_back(_sps[1]); // profile + extra_data.push_back(_sps[2]); // compat + extra_data.push_back(_sps[3]); // level + extra_data.push_back((char)0xff); // 6 bits reserved + 2 bits nal size length - 1 (11) + extra_data.push_back((char)0xe1); // 3 bits reserved + 5 bits number of sps (00001) + // sps + uint16_t size = (uint16_t)_sps.size(); + size = htons(size); + extra_data.append((char *)&size, 2); + extra_data.append(_sps); + // pps + extra_data.push_back(1); // version + size = (uint16_t)_pps.size(); + size = htons(size); + extra_data.append((char *)&size, 2); + extra_data.append(_pps); + return std::make_shared(std::move(extra_data)); +#endif +} + +void H264Track::setExtraData(const uint8_t *data, size_t bytes) { +#ifdef ENABLE_MP4 + struct mpeg4_avc_t avc; + memset(&avc, 0, sizeof(avc)); + if (mpeg4_avc_decoder_configuration_record_load(data, bytes, &avc) > 0) { + std::vector config(bytes * 2); + int size = mpeg4_avc_to_nalu(&avc, config.data(), bytes * 2); + if (size > 4) { + splitH264((char *)config.data(), size, 4, [&](const char *ptr, size_t len, size_t prefix) { + inputFrame_l(std::make_shared((char *)ptr, len, 0, 0, prefix)); + }); + update(); + } + } +#else + CHECK(bytes >= 8); // 6 + 2 + size_t offset = 6; + + uint16_t sps_size = data[offset] << 8 | data[offset + 1]; + auto sps_ptr = data + offset + 2; + offset += (2 + sps_size); + CHECK(bytes >= offset + 2); // + pps_size + _sps.assign((char *)sps_ptr, sps_size); + + uint16_t pps_size = data[offset] << 8 | data[offset + 1]; + auto pps_ptr = data + offset + 2; + offset += (2 + pps_size); + CHECK(bytes >= offset); + _pps.assign((char *)pps_ptr, pps_size); + update(); +#endif +} + bool H264Track::update() { return getAVCInfo(_sps, _width, _height, _fps); } -void H264Track::onReady() { - if (!getAVCInfo(_sps, _width, _height, _fps)) { - _sps.clear(); - _pps.clear(); - } -} - -Track::Ptr H264Track::clone() { - return std::make_shared::type>(*this); +Track::Ptr H264Track::clone() const { + return std::make_shared(*this); } bool H264Track::inputFrame_l(const Frame::Ptr &frame) { @@ -218,7 +277,7 @@ bool H264Track::inputFrame_l(const Frame::Ptr &frame) { } if (_width == 0 && ready()) { - onReady(); + update(); } return ret; } @@ -230,6 +289,7 @@ void H264Track::insertConfigFrame(const Frame::Ptr &frame) { spsFrame->_buffer.assign("\x00\x00\x00\x01", 4); spsFrame->_buffer.append(_sps); spsFrame->_dts = frame->dts(); + spsFrame->setIndex(frame->getIndex()); VideoTrack::inputFrame(spsFrame); } @@ -239,20 +299,19 @@ void H264Track::insertConfigFrame(const Frame::Ptr &frame) { ppsFrame->_buffer.assign("\x00\x00\x00\x01", 4); ppsFrame->_buffer.append(_pps); ppsFrame->_dts = frame->dts(); + ppsFrame->setIndex(frame->getIndex()); VideoTrack::inputFrame(ppsFrame); } } class H264Sdp : public Sdp { public: - H264Sdp(const string &strSPS, const string &strPPS, int bitrate, int payload_type = 96) - : Sdp(90000, payload_type) { - //视频通道 + H264Sdp(const string &strSPS, const string &strPPS, int payload_type, int bitrate) : Sdp(90000, payload_type) { _printer << "m=video 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << 90000 << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecH264) << "/" << 90000 << "\r\n"; /** Single NAI Unit Mode = 0. // Single NAI mode (Only nals from 1-23 are allowed) @@ -275,23 +334,76 @@ public: _printer << "; sprop-parameter-sets="; _printer << encodeBase64(strSPS) << ","; _printer << encodeBase64(strPPS) << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackVideo << "\r\n"; } string getSdp() const { return _printer; } - CodecId getCodecId() const { return CodecH264; } - private: _StrPrinter _printer; }; -Sdp::Ptr H264Track::getSdp() { +Sdp::Ptr H264Track::getSdp(uint8_t payload_type) const { if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } - return std::make_shared(getSps(), getPps(), getBitRate() / 1024); + return std::make_shared(_sps, _pps, payload_type, getBitRate() / 1024); } +namespace { + +CodecId getCodec() { + return CodecH264; +} + +Track::Ptr getTrackByCodecId(int sample_rate, int channels, int sample_bit) { + return std::make_shared(); +} + +Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track) { + //a=fmtp:96 packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9oBQBboQAAAAwBAAAAPI8YMqA==,aM48gA== + auto map = Parser::parseArgs(track->_fmtp, ";", "="); + auto sps_pps = map["sprop-parameter-sets"]; + string base64_SPS = findSubString(sps_pps.data(), NULL, ","); + string base64_PPS = findSubString(sps_pps.data(), ",", NULL); + auto sps = decodeBase64(base64_SPS); + auto pps = decodeBase64(base64_PPS); + if (sps.empty() || pps.empty()) { + //如果sdp里面没有sps/pps,那么可能在后续的rtp里面恢复出sps/pps + return std::make_shared(); + } + return std::make_shared(sps, pps, 0, 0); +} + +RtpCodec::Ptr getRtpEncoderByCodecId(uint8_t pt) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpDecoderByCodecId() { + return std::make_shared(); +} + +RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +Frame::Ptr getFrameFromPtr(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return std::make_shared((char *)data, bytes, dts, pts, prefixSize(data, bytes)); +} + +} // namespace + +CodecPlugin h264_plugin = { getCodec, + getTrackByCodecId, + getTrackBySdp, + getRtpEncoderByCodecId, + getRtpDecoderByCodecId, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtr }; + } // namespace mediakit diff --git a/src/Extension/H264.h b/ext-codec/H264.h similarity index 78% rename from src/Extension/H264.h rename to ext-codec/H264.h index 0afe593d..cf054da0 100644 --- a/src/Extension/H264.h +++ b/ext-codec/H264.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,14 +11,13 @@ #ifndef ZLMEDIAKIT_H264_H #define ZLMEDIAKIT_H264_H -#include "Frame.h" -#include "Track.h" +#include "Extension/Frame.h" +#include "Extension/Track.h" #define H264_TYPE(v) ((uint8_t)(v) & 0x1F) namespace mediakit{ -bool getAVCInfo(const std::string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); void splitH264(const char *ptr, size_t len, size_t prefix, const std::function &cb); size_t prefixSize(const char *ptr, size_t len); @@ -43,8 +42,6 @@ public: this->_codec_id = CodecH264; } - ~H264FrameHelper() override = default; - bool keyFrame() const override { auto nal_ptr = (uint8_t *) this->data() + this->prefixSize(); return H264_TYPE(*nal_ptr) == NAL_IDR && decodeAble(); @@ -107,33 +104,21 @@ public: * @param sps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01 * @param pps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01 */ - H264Track(const std::string &sps,const std::string &pps,int sps_prefix_len = 4,int pps_prefix_len = 4); + H264Track(const std::string &sps, const std::string &pps, int sps_prefix_len = 4, int pps_prefix_len = 4); - /** - * 构造h264类型的媒体 - * @param sps sps帧 - * @param pps pps帧 - */ - H264Track(const Frame::Ptr &sps,const Frame::Ptr &pps); - - /** - * 返回不带0x00 00 00 01头的sps/pps - */ - const std::string &getSps() const; - const std::string &getPps() const; - - bool ready() override; + bool ready() const override; CodecId getCodecId() const override; int getVideoHeight() const override; int getVideoWidth() const override; float getVideoFps() const override; bool inputFrame(const Frame::Ptr &frame) override; + toolkit::Buffer::Ptr getExtraData() const override; + void setExtraData(const uint8_t *data, size_t size) override; bool update() override; private: - void onReady(); - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; bool inputFrame_l(const Frame::Ptr &frame); void insertConfigFrame(const Frame::Ptr &frame); diff --git a/ext-codec/H264Rtmp.cpp b/ext-codec/H264Rtmp.cpp new file mode 100644 index 00000000..05098779 --- /dev/null +++ b/ext-codec/H264Rtmp.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#include "Rtmp/utils.h" +#include "H264Rtmp.h" + +using namespace std; +using namespace toolkit; + +namespace mediakit { + +void H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { + if (pkt->isConfigFrame()) { + CHECK(pkt->size() > 5); + getTrack()->setExtraData((uint8_t *)pkt->data() + 5, pkt->size() - 5); + return; + } + + CHECK(pkt->size() > 9); + uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2); + int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; + auto pts = pkt->time_stamp + cts; + splitFrame((uint8_t *)pkt->data() + 5, pkt->size() - 5, pkt->time_stamp, pts); +} + +void H264RtmpDecoder::splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts) { + auto end = data + size; + while (data + 4 < end) { + uint32_t frame_len = load_be32(data); + data += 4; + if (data + frame_len > end) { + break; + } + outputFrame((const char *)data, frame_len, dts, pts); + data += frame_len; + } +} + +void H264RtmpDecoder::outputFrame(const char *data, size_t len, uint32_t dts, uint32_t pts) { + auto frame = FrameImp::create(); + frame->_prefix_size = 4; + frame->_dts = dts; + frame->_pts = pts; + frame->_buffer.assign("\x00\x00\x00\x01", 4); // 添加264头 + frame->_buffer.append(data, len); + RtmpCodec::inputFrame(frame); +} + +//////////////////////////////////////////////////////////////////////// + +void H264RtmpEncoder::flush() { + inputFrame(nullptr); +} + +bool H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { + if (!_rtmp_packet) { + _rtmp_packet = RtmpPacket::create(); + //flags/not config/cts预占位 + _rtmp_packet->buffer.resize(5); + } + + return _merger.inputFrame(frame, [this](uint64_t dts, uint64_t pts, const Buffer::Ptr &, bool have_key_frame) { + // flags + _rtmp_packet->buffer[0] = (uint8_t)RtmpVideoCodec::h264 | ((uint8_t)(have_key_frame ? RtmpFrameType::key_frame : RtmpFrameType::inter_frame) << 4); + _rtmp_packet->buffer[1] = (uint8_t)RtmpH264PacketType::h264_nalu; + int32_t cts = pts - dts; + // cts + set_be24(&_rtmp_packet->buffer[2], cts); + _rtmp_packet->time_stamp = dts; + _rtmp_packet->body_size = _rtmp_packet->buffer.size(); + _rtmp_packet->chunk_id = CHUNK_VIDEO; + _rtmp_packet->stream_index = STREAM_MEDIA; + _rtmp_packet->type_id = MSG_VIDEO; + // 输出rtmp packet + RtmpCodec::inputRtmp(_rtmp_packet); + _rtmp_packet = nullptr; + }, &_rtmp_packet->buffer); +} + +void H264RtmpEncoder::makeConfigPacket() { + auto flags = (uint8_t)RtmpVideoCodec::h264; + flags |= ((uint8_t)RtmpFrameType::key_frame << 4); + auto pkt = RtmpPacket::create(); + // header + pkt->buffer.push_back(flags); + pkt->buffer.push_back((uint8_t)RtmpH264PacketType::h264_config_header); + // cts + pkt->buffer.append("\x0\x0\x0", 3); + // AVCDecoderConfigurationRecord start + auto extra_data = getTrack()->getExtraData(); + CHECK(extra_data); + pkt->buffer.append(extra_data->data(), extra_data->size()); + + pkt->body_size = pkt->buffer.size(); + pkt->chunk_id = CHUNK_VIDEO; + pkt->stream_index = STREAM_MEDIA; + pkt->time_stamp = 0; + pkt->type_id = MSG_VIDEO; + RtmpCodec::inputRtmp(pkt); +} + +}//namespace mediakit diff --git a/src/Extension/H264Rtmp.h b/ext-codec/H264Rtmp.h similarity index 60% rename from src/Extension/H264Rtmp.h rename to ext-codec/H264Rtmp.h index 5849ba2a..f610f47c 100644 --- a/src/Extension/H264Rtmp.h +++ b/ext-codec/H264Rtmp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,11 +11,11 @@ #ifndef ZLMEDIAKIT_H264RTMPCODEC_H #define ZLMEDIAKIT_H264RTMPCODEC_H +#include "H264.h" #include "Rtmp/RtmpCodec.h" #include "Extension/Track.h" -#include "Extension/H264.h" -namespace mediakit{ +namespace mediakit { /** * h264 Rtmp解码类 * 将 h264 over rtmp 解复用出 h264-Frame @@ -24,8 +24,7 @@ class H264RtmpDecoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - H264RtmpDecoder(); - ~H264RtmpDecoder() {} + H264RtmpDecoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入264 Rtmp包 @@ -33,24 +32,15 @@ public: */ void inputRtmp(const RtmpPacket::Ptr &rtmp) override; - CodecId getCodecId() const override{ - return CodecH264; - } - -protected: - void onGetH264(const char *data, size_t len, uint32_t dts, uint32_t pts); - H264Frame::Ptr obtainFrame(); - -protected: - H264Frame::Ptr _h264frame; - std::string _sps; - std::string _pps; +private: + void outputFrame(const char *data, size_t len, uint32_t dts, uint32_t pts); + void splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts); }; /** * 264 Rtmp打包类 */ -class H264RtmpEncoder : public H264RtmpDecoder{ +class H264RtmpEncoder : public RtmpCodec { public: using Ptr = std::shared_ptr; @@ -60,8 +50,7 @@ public: * 那么inputFrame时可以不输入sps pps * @param track */ - H264RtmpEncoder(const Track::Ptr &track); - ~H264RtmpEncoder() = default; + H264RtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入264帧,可以不带sps pps @@ -80,13 +69,8 @@ public: void makeConfigPacket() override; private: - void makeVideoConfigPkt(); - -private: - bool _got_config_frame = false; - H264Track::Ptr _track; RtmpPacket::Ptr _rtmp_packet; - FrameMerger _merger{FrameMerger::mp4_nal_size}; + FrameMerger _merger { FrameMerger::mp4_nal_size }; }; }//namespace mediakit diff --git a/src/Extension/H264Rtp.cpp b/ext-codec/H264Rtp.cpp similarity index 93% rename from src/Extension/H264Rtp.cpp rename to ext-codec/H264Rtp.cpp index 442205a6..1972a040 100644 --- a/src/Extension/H264Rtp.cpp +++ b/ext-codec/H264Rtp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -192,10 +192,6 @@ void H264RtpDecoder::outputFrame(const RtpPacket::Ptr &rtp, const H264Frame::Ptr //////////////////////////////////////////////////////////////////////// -H264RtpEncoder::H264RtpEncoder(uint32_t ssrc, uint32_t mtu, uint32_t sample_rate, uint8_t pt, uint8_t interleaved) - : RtpInfo(ssrc, mtu, sample_rate, pt, interleaved) { -} - void H264RtpEncoder::insertConfigFrame(uint64_t pts){ if (!_sps || !_pps) { return; @@ -206,7 +202,7 @@ void H264RtpEncoder::insertConfigFrame(uint64_t pts){ } void H264RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ - if (len + 3 <= getMaxSize()) { + if (len + 3 <= getRtpInfo().getMaxSize()) { // 采用STAP-A/Single NAL unit packet per H.264 模式 packRtpSmallFrame(ptr, len, pts, is_mark, gop_pos); } else { @@ -216,7 +212,7 @@ void H264RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_ } void H264RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ - auto packet_size = getMaxSize() - 2; + auto packet_size = getRtpInfo().getMaxSize() - 2; if (len <= packet_size + 1) { // 小于FU-A打包最小字节长度要求,采用STAP-A/Single NAL unit packet per H.264 模式 packRtpSmallFrame(ptr, len, pts, is_mark, gop_pos); @@ -238,7 +234,7 @@ void H264RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool i } //传入nullptr先不做payload的内存拷贝 - auto rtp = makeRtp(getTrackType(), nullptr, packet_size + 2, fu_flags->end_bit && is_mark, pts); + auto rtp = getRtpInfo().makeRtp(TrackVideo, nullptr, packet_size + 2, fu_flags->end_bit && is_mark, pts); //rtp payload 负载部分 uint8_t *payload = rtp->getPayload(); //FU-A 第1个字节 @@ -266,7 +262,7 @@ void H264RtpEncoder::packRtpSmallFrame(const char *data, size_t len, uint64_t pt void H264RtpEncoder::packRtpStapA(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ // 如果帧长度不超过mtu,为了兼容性 webrtc,采用STAP-A模式打包 - auto rtp = makeRtp(getTrackType(), nullptr, len + 3, is_mark, pts); + auto rtp = getRtpInfo().makeRtp(TrackVideo, nullptr, len + 3, is_mark, pts); uint8_t *payload = rtp->getPayload(); //STAP-A payload[0] = (ptr[0] & (~0x1F)) | 24; @@ -279,7 +275,7 @@ void H264RtpEncoder::packRtpStapA(const char *ptr, size_t len, uint64_t pts, boo void H264RtpEncoder::packRtpSingleNalu(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos) { // Single NAL unit packet per H.264 模式 - RtpCodec::inputRtp(makeRtp(getTrackType(), data, len, is_mark, pts), gop_pos); + RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackVideo, data, len, is_mark, pts), gop_pos); } bool H264RtpEncoder::inputFrame(const Frame::Ptr &frame) { diff --git a/src/Extension/H264Rtp.h b/ext-codec/H264Rtp.h similarity index 72% rename from src/Extension/H264Rtp.h rename to ext-codec/H264Rtp.h index 98d49cda..3f98be07 100644 --- a/src/Extension/H264Rtp.h +++ b/ext-codec/H264Rtp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,12 +11,12 @@ #ifndef ZLMEDIAKIT_H264RTPCODEC_H #define ZLMEDIAKIT_H264RTPCODEC_H -#include "Rtsp/RtpCodec.h" -#include "Extension/H264.h" +#include "H264.h" // for DtsGenerator #include "Common/Stamp.h" +#include "Rtsp/RtpCodec.h" -namespace mediakit{ +namespace mediakit { /** * h264 rtp解码类 @@ -28,7 +28,6 @@ public: using Ptr = std::shared_ptr; H264RtpDecoder(); - ~H264RtpDecoder() override = default; /** * 输入264 rtp包 @@ -37,10 +36,6 @@ public: */ bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override; - CodecId getCodecId() const override{ - return CodecH264; - } - private: bool singleFrame(const RtpPacket::Ptr &rtp, const uint8_t *ptr, ssize_t size, uint64_t stamp); bool unpackStapA(const RtpPacket::Ptr &rtp, const uint8_t *ptr, ssize_t size, uint64_t stamp); @@ -62,26 +57,11 @@ private: /** * 264 rtp打包类 */ -class H264RtpEncoder : public H264RtpDecoder ,public RtpInfo{ +class H264RtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr; /** - * @param ssrc ssrc - * @param mtu mtu大小 - * @param sample_rate 采样率,强制为90000 - * @param pt pt类型 - * @param interleaved rtsp interleaved - */ - H264RtpEncoder(uint32_t ssrc, - uint32_t mtu = 1400, - uint32_t sample_rate = 90000, - uint8_t pt = 96, - uint8_t interleaved = TrackVideo * 2); - - ~H264RtpEncoder() override = default; - - /** * 输入264帧 * @param frame 帧数据,必须 */ diff --git a/src/Extension/H265.cpp b/ext-codec/H265.cpp similarity index 57% rename from src/Extension/H265.cpp rename to ext-codec/H265.cpp index 926ab2a4..3a999255 100644 --- a/src/Extension/H265.cpp +++ b/ext-codec/H265.cpp @@ -1,16 +1,24 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "H265.h" +#include "H265Rtp.h" +#include "H265Rtmp.h" #include "SPSParser.h" #include "Util/base64.h" +#include "Common/Parser.h" +#include "Extension/Factory.h" + +#ifdef ENABLE_MP4 +#include "mpeg4-hevc.h" +#endif using namespace std; using namespace toolkit; @@ -58,19 +66,7 @@ H265Track::H265Track(const string &vps,const string &sps, const string &pps,int _vps = vps.substr(vps_prefix_len); _sps = sps.substr(sps_prefix_len); _pps = pps.substr(pps_prefix_len); - onReady(); -} - -const string &H265Track::getVps() const { - return _vps; -} - -const string &H265Track::getSps() const { - return _sps; -} - -const string &H265Track::getPps() const { - return _pps; + update(); } CodecId H265Track::getCodecId() const { @@ -89,7 +85,7 @@ float H265Track::getVideoFps() const { return _fps; } -bool H265Track::ready() { +bool H265Track::ready() const { return !_vps.empty() && !_sps.empty() && !_pps.empty(); } @@ -139,25 +135,58 @@ bool H265Track::inputFrame_l(const Frame::Ptr &frame) { } } if (_width == 0 && ready()) { - onReady(); + update(); } return ret; } +toolkit::Buffer::Ptr H265Track::getExtraData() const { + CHECK(ready()); +#ifdef ENABLE_MP4 + struct mpeg4_hevc_t hevc; + memset(&hevc, 0, sizeof(hevc)); + string vps_sps_pps = string("\x00\x00\x00\x01", 4) + _vps + string("\x00\x00\x00\x01", 4) + _sps + string("\x00\x00\x00\x01", 4) + _pps; + h265_annexbtomp4(&hevc, vps_sps_pps.data(), (int) vps_sps_pps.size(), NULL, 0, NULL, NULL); + + std::string extra_data; + extra_data.resize(1024); + auto extra_data_size = mpeg4_hevc_decoder_configuration_record_save(&hevc, (uint8_t *)extra_data.data(), extra_data.size()); + if (extra_data_size == -1) { + WarnL << "生成H265 extra_data 失败"; + return nullptr; + } + return std::make_shared(std::move(extra_data)); +#else + WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265的支持不完善"; + return nullptr; +#endif +} + +void H265Track::setExtraData(const uint8_t *data, size_t bytes) { +#ifdef ENABLE_MP4 + struct mpeg4_hevc_t hevc; + memset(&hevc, 0, sizeof(hevc)); + if (mpeg4_hevc_decoder_configuration_record_load(data, bytes, &hevc) > 0) { + std::vector config(bytes * 2); + int size = mpeg4_hevc_to_nalu(&hevc, config.data(), bytes * 2); + if (size > 4) { + splitH264((char *)config.data(), size, 4, [&](const char *ptr, size_t len, size_t prefix) { + inputFrame_l(std::make_shared((char *)ptr, len, 0, 0, prefix)); + }); + update(); + } + } +#else + WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265的支持不完善"; +#endif +} + bool H265Track::update() { return getHEVCInfo(_vps, _sps, _width, _height, _fps); } -void H265Track::onReady() { - if (!getHEVCInfo(_vps, _sps, _width, _height, _fps)) { - _vps.clear(); - _sps.clear(); - _pps.clear(); - } -} - -Track::Ptr H265Track::clone() { - return std::make_shared::type>(*this); +Track::Ptr H265Track::clone() const { + return std::make_shared(*this); } void H265Track::insertConfigFrame(const Frame::Ptr &frame) { @@ -170,6 +199,7 @@ void H265Track::insertConfigFrame(const Frame::Ptr &frame) { vpsFrame->_buffer.assign("\x00\x00\x00\x01", 4); vpsFrame->_buffer.append(_vps); vpsFrame->_dts = frame->dts(); + vpsFrame->setIndex(frame->getIndex()); VideoTrack::inputFrame(vpsFrame); } if (!_sps.empty()) { @@ -178,6 +208,7 @@ void H265Track::insertConfigFrame(const Frame::Ptr &frame) { spsFrame->_buffer.assign("\x00\x00\x00\x01", 4); spsFrame->_buffer.append(_sps); spsFrame->_dts = frame->dts(); + spsFrame->setIndex(frame->getIndex()); VideoTrack::inputFrame(spsFrame); } @@ -187,6 +218,7 @@ void H265Track::insertConfigFrame(const Frame::Ptr &frame) { ppsFrame->_buffer.assign("\x00\x00\x00\x01", 4); ppsFrame->_buffer.append(_pps); ppsFrame->_dts = frame->dts(); + ppsFrame->setIndex(frame->getIndex()); VideoTrack::inputFrame(ppsFrame); } } @@ -205,17 +237,13 @@ public: * @param payload_type rtp payload type 默认96 * @param bitrate 比特率 */ - H265Sdp(const string &strVPS, - const string &strSPS, - const string &strPPS, - int bitrate = 4000, - int payload_type = 96) : Sdp(90000,payload_type) { + H265Sdp(const string &strVPS, const string &strSPS, const string &strPPS, int payload_type, int bitrate) : Sdp(90000, payload_type) { //视频通道 _printer << "m=video 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << 90000 << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecH265) << "/" << 90000 << "\r\n"; _printer << "a=fmtp:" << payload_type << " "; _printer << "sprop-vps="; _printer << encodeBase64(strVPS) << "; "; @@ -223,27 +251,75 @@ public: _printer << encodeBase64(strSPS) << "; "; _printer << "sprop-pps="; _printer << encodeBase64(strPPS) << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackVideo << "\r\n"; } - string getSdp() const override { - return _printer; - } + string getSdp() const override { return _printer; } - CodecId getCodecId() const override { - return CodecH265; - } private: _StrPrinter _printer; }; -Sdp::Ptr H265Track::getSdp() { - if(!ready()){ +Sdp::Ptr H265Track::getSdp(uint8_t payload_type) const { + if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } - return std::make_shared(getVps(), getSps(), getPps(), getBitRate() / 1024); + return std::make_shared(_vps, _sps, _pps, payload_type, getBitRate() / 1024); } +namespace { + +CodecId getCodec() { + return CodecH265; +} + +Track::Ptr getTrackByCodecId(int sample_rate, int channels, int sample_bit) { + return std::make_shared(); +} + +Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track) { + // a=fmtp:96 sprop-sps=QgEBAWAAAAMAsAAAAwAAAwBdoAKAgC0WNrkky/AIAAADAAgAAAMBlQg=; sprop-pps=RAHA8vA8kAA= + auto map = Parser::parseArgs(track->_fmtp, ";", "="); + auto vps = decodeBase64(map["sprop-vps"]); + auto sps = decodeBase64(map["sprop-sps"]); + auto pps = decodeBase64(map["sprop-pps"]); + if (sps.empty() || pps.empty()) { + // 如果sdp里面没有sps/pps,那么可能在后续的rtp里面恢复出sps/pps + return std::make_shared(); + } + return std::make_shared(vps, sps, pps, 0, 0, 0); +} + +RtpCodec::Ptr getRtpEncoderByCodecId(uint8_t pt) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpDecoderByCodecId() { + return std::make_shared(); +} + +RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +Frame::Ptr getFrameFromPtr(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return std::make_shared((char *)data, bytes, dts, pts, prefixSize(data, bytes)); +} + +} // namespace + +CodecPlugin h265_plugin = { getCodec, + getTrackByCodecId, + getTrackBySdp, + getRtpEncoderByCodecId, + getRtpDecoderByCodecId, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtr }; + }//namespace mediakit diff --git a/src/Extension/H265.h b/ext-codec/H265.h similarity index 85% rename from src/Extension/H265.h rename to ext-codec/H265.h index 912f1f46..50775727 100644 --- a/src/Extension/H265.h +++ b/ext-codec/H265.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,16 +11,14 @@ #ifndef ZLMEDIAKIT_H265_H #define ZLMEDIAKIT_H265_H -#include "Frame.h" -#include "Track.h" #include "H264.h" +#include "Extension/Track.h" +#include "Extension/Frame.h" #define H265_TYPE(v) (((uint8_t)(v) >> 1) & 0x3f) namespace mediakit { -bool getHEVCInfo(const std::string &strVps, const std::string &strSps, int &iVideoWidth, int &iVideoHeight, float &iVideoFps); - template class H265FrameHelper : public Parent{ public: @@ -64,8 +62,6 @@ public: this->_codec_id = CodecH265; } - ~H265FrameHelper() override = default; - bool keyFrame() const override { auto nal_ptr = (uint8_t *) this->data() + this->prefixSize(); auto type = H265_TYPE(*nal_ptr); @@ -137,25 +133,19 @@ public: */ H265Track(const std::string &vps,const std::string &sps, const std::string &pps,int vps_prefix_len = 4, int sps_prefix_len = 4, int pps_prefix_len = 4); - /** - * 返回不带0x00 00 00 01头的vps/sps/pps - */ - const std::string &getVps() const; - const std::string &getSps() const; - const std::string &getPps() const; - - bool ready() override; + bool ready() const override; CodecId getCodecId() const override; int getVideoWidth() const override; int getVideoHeight() const override; float getVideoFps() const override; bool inputFrame(const Frame::Ptr &frame) override; + toolkit::Buffer::Ptr getExtraData() const override; + void setExtraData(const uint8_t *data, size_t size) override; bool update() override; private: - void onReady(); - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; bool inputFrame_l(const Frame::Ptr &frame); void insertConfigFrame(const Frame::Ptr &frame); diff --git a/ext-codec/H265Rtmp.cpp b/ext-codec/H265Rtmp.cpp new file mode 100644 index 00000000..9799849d --- /dev/null +++ b/ext-codec/H265Rtmp.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#include "H265Rtmp.h" +#include "Rtmp/utils.h" +#include "Common/config.h" +#ifdef ENABLE_MP4 +#include "mpeg4-hevc.h" +#endif // ENABLE_MP4 + +using namespace std; +using namespace toolkit; + +namespace mediakit { + +void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { + if (_info.codec == CodecInvalid) { + // 先判断是否为增强型rtmp + parseVideoRtmpPacket((uint8_t *)pkt->data(), pkt->size(), &_info); + } + + if (_info.is_enhanced) { + // 增强型rtmp + parseVideoRtmpPacket((uint8_t *)pkt->data(), pkt->size(), &_info); + if (!_info.is_enhanced || _info.codec != CodecH265) { + throw std::invalid_argument("Invalid enhanced-rtmp hevc packet!"); + } + + switch (_info.video.pkt_type) { + case RtmpPacketType::PacketTypeSequenceStart: { + getTrack()->setExtraData((uint8_t *)pkt->data() + RtmpPacketInfo::kEnhancedRtmpHeaderSize, pkt->size() - RtmpPacketInfo::kEnhancedRtmpHeaderSize); + break; + } + + case RtmpPacketType::PacketTypeCodedFramesX: + case RtmpPacketType::PacketTypeCodedFrames: { + auto data = (uint8_t *)pkt->data() + RtmpPacketInfo::kEnhancedRtmpHeaderSize; + auto size = pkt->size() - RtmpPacketInfo::kEnhancedRtmpHeaderSize; + auto pts = pkt->time_stamp; + CHECK(size > 3); + if (RtmpPacketType::PacketTypeCodedFrames == _info.video.pkt_type) { + // SI24 = [CompositionTime Offset] + int32_t cts = (((data[0] << 16) | (data[1] << 8) | (data[2])) + 0xff800000) ^ 0xff800000; + pts += cts; + data += 3; + size -= 3; + } + CHECK(size > 4); + splitFrame(data, size, pkt->time_stamp, pts); + break; + } + default: WarnL << "Unknown pkt_type: " << (int)_info.video.pkt_type; break; + } + return; + } + + // 国内扩展(12) H265 rtmp + if (pkt->isConfigFrame()) { + CHECK(pkt->size() > 5); + getTrack()->setExtraData((uint8_t *)pkt->data() + 5, pkt->size() - 5); + return; + } + + CHECK(pkt->size() > 9); + uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2); + int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; + auto pts = pkt->time_stamp + cts; + splitFrame((uint8_t *)pkt->data() + 5, pkt->size() - 5, pkt->time_stamp, pts); +} + +void H265RtmpDecoder::splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts) { + auto end = data + size; + while (data + 4 < end) { + uint32_t frame_len = load_be32(data); + data += 4; + if (data + frame_len > end) { + break; + } + outputFrame((const char *)data, frame_len, dts, pts); + data += frame_len; + } +} + +inline void H265RtmpDecoder::outputFrame(const char *data, size_t size, uint32_t dts, uint32_t pts) { + auto frame = FrameImp::create(); + frame->_prefix_size = 4; + frame->_dts = dts; + frame->_pts = pts; + frame->_buffer.assign("\x00\x00\x00\x01", 4); // 添加265头 + frame->_buffer.append(data, size); + RtmpCodec::inputFrame(frame); +} + +//////////////////////////////////////////////////////////////////////// + +void H265RtmpEncoder::flush() { + inputFrame(nullptr); +} + +bool H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) { + if (!_rtmp_packet) { + _rtmp_packet = RtmpPacket::create(); + GET_CONFIG(bool, enhanced, Rtmp::kEnhanced); + _rtmp_packet->buffer.resize((enhanced ? RtmpPacketInfo::kEnhancedRtmpHeaderSize : 2) + 3); + } + + return _merger.inputFrame(frame, [this](uint64_t dts, uint64_t pts, const Buffer::Ptr &, bool have_key_frame) { + GET_CONFIG(bool, enhanced, Rtmp::kEnhanced); + if (enhanced) { + auto header = (RtmpVideoHeaderEnhanced *)_rtmp_packet->data(); + header->enhanced = 1; + header->pkt_type = (int)RtmpPacketType::PacketTypeCodedFrames; + header->frame_type = have_key_frame ? (int)RtmpFrameType::key_frame : (int)RtmpFrameType::inter_frame; + header->fourcc = htonl((uint32_t)RtmpVideoCodec::fourcc_hevc); + } else { + // flags + _rtmp_packet->buffer[0] = (uint8_t)RtmpVideoCodec::h265 | ((uint8_t)(have_key_frame ? RtmpFrameType::key_frame : RtmpFrameType::inter_frame) << 4); + _rtmp_packet->buffer[1] = (uint8_t)RtmpH264PacketType::h264_nalu; + } + + int32_t cts = pts - dts; + // cts + set_be24(&_rtmp_packet->buffer[enhanced ? 5 : 2], cts); + _rtmp_packet->time_stamp = dts; + _rtmp_packet->body_size = _rtmp_packet->buffer.size(); + _rtmp_packet->chunk_id = CHUNK_VIDEO; + _rtmp_packet->stream_index = STREAM_MEDIA; + _rtmp_packet->type_id = MSG_VIDEO; + // 输出rtmp packet + RtmpCodec::inputRtmp(_rtmp_packet); + _rtmp_packet = nullptr; + }, &_rtmp_packet->buffer); +} + +void H265RtmpEncoder::makeConfigPacket() { + auto pkt = RtmpPacket::create(); + GET_CONFIG(bool, enhanced, Rtmp::kEnhanced); + if (enhanced) { + pkt->buffer.resize(RtmpPacketInfo::kEnhancedRtmpHeaderSize); + auto header = (RtmpVideoHeaderEnhanced *)pkt->data(); + header->enhanced = 1; + header->pkt_type = (int)RtmpPacketType::PacketTypeSequenceStart; + header->frame_type = (int)RtmpFrameType::key_frame; + header->fourcc = htonl((uint32_t)RtmpVideoCodec::fourcc_hevc); + } else { + auto flags = (uint8_t)RtmpVideoCodec::h265; + flags |= ((uint8_t)RtmpFrameType::key_frame << 4); + // header + pkt->buffer.push_back(flags); + pkt->buffer.push_back((uint8_t)RtmpH264PacketType::h264_config_header); + // cts + pkt->buffer.append("\x0\x0\x0", 3); + } + + // HEVCDecoderConfigurationRecord + auto extra_data = getTrack()->getExtraData(); + CHECK(extra_data); + pkt->buffer.append(extra_data->data(), extra_data->size()); + pkt->body_size = pkt->buffer.size(); + pkt->chunk_id = CHUNK_VIDEO; + pkt->stream_index = STREAM_MEDIA; + pkt->time_stamp = 0; + pkt->type_id = MSG_VIDEO; + RtmpCodec::inputRtmp(pkt); +} + +} // namespace mediakit diff --git a/src/Extension/H265Rtmp.h b/ext-codec/H265Rtmp.h similarity index 65% rename from src/Extension/H265Rtmp.h rename to ext-codec/H265Rtmp.h index 527728f6..36c4d846 100644 --- a/src/Extension/H265Rtmp.h +++ b/ext-codec/H265Rtmp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,9 +11,9 @@ #ifndef ZLMEDIAKIT_H265RTMPCODEC_H #define ZLMEDIAKIT_H265RTMPCODEC_H +#include "H265.h" #include "Rtmp/RtmpCodec.h" #include "Extension/Track.h" -#include "Extension/H265.h" namespace mediakit { /** @@ -24,8 +24,7 @@ class H265RtmpDecoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - H265RtmpDecoder(); - ~H265RtmpDecoder() = default; + H265RtmpDecoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入265 Rtmp包 @@ -33,23 +32,18 @@ public: */ void inputRtmp(const RtmpPacket::Ptr &rtmp) override; - CodecId getCodecId() const override { return CodecH265; } - protected: - H265Frame::Ptr obtainFrame(); - - void onGetH265(const char *data, size_t size, uint32_t dts, uint32_t pts); + void outputFrame(const char *data, size_t size, uint32_t dts, uint32_t pts); void splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts); protected: RtmpPacketInfo _info; - H265Frame::Ptr _h265frame; }; /** * 265 Rtmp打包类 */ -class H265RtmpEncoder : public H265RtmpDecoder { +class H265RtmpEncoder : public RtmpCodec { public: using Ptr = std::shared_ptr; @@ -59,8 +53,7 @@ public: * 那么inputFrame时可以不输入sps pps * @param track */ - H265RtmpEncoder(const Track::Ptr &track); - ~H265RtmpEncoder() = default; + H265RtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入265帧,可以不带sps pps @@ -79,14 +72,6 @@ public: void makeConfigPacket() override; private: - void makeVideoConfigPkt(); - -private: - bool _got_config_frame = false; - std::string _vps; - std::string _sps; - std::string _pps; - H265Track::Ptr _track; RtmpPacket::Ptr _rtmp_packet; FrameMerger _merger { FrameMerger::mp4_nal_size }; }; diff --git a/src/Extension/H265Rtp.cpp b/ext-codec/H265Rtp.cpp similarity index 93% rename from src/Extension/H265Rtp.cpp rename to ext-codec/H265Rtp.cpp index 22866ff4..6f05e67f 100644 --- a/src/Extension/H265Rtp.cpp +++ b/ext-codec/H265Rtp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -248,20 +248,8 @@ void H265RtpDecoder::outputFrame(const RtpPacket::Ptr &rtp, const H265Frame::Ptr //////////////////////////////////////////////////////////////////////// -H265RtpEncoder::H265RtpEncoder(uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PayloadType, - uint8_t ui8Interleaved) : - RtpInfo(ui32Ssrc, - ui32MtuSize, - ui32SampleRate, - ui8PayloadType, - ui8Interleaved) { -} - void H265RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ - auto max_size = getMaxSize() - 3; + auto max_size = getRtpInfo().getMaxSize() - 3; auto nal_type = H265_TYPE(ptr[0]); //获取NALU的5bit 帧类型 unsigned char s_e_flags; bool fu_start = true; @@ -283,7 +271,7 @@ void H265RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool i { // 传入nullptr先不做payload的内存拷贝 - auto rtp = makeRtp(getTrackType(), nullptr, max_size + 3, mark_bit, pts); + auto rtp = getRtpInfo().makeRtp(TrackVideo, nullptr, max_size + 3, mark_bit, pts); // rtp payload 负载部分 uint8_t *payload = rtp->getPayload(); // FU 第1个字节,表明为FU @@ -304,9 +292,9 @@ void H265RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool i } void H265RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ - if (len <= getMaxSize()) { + if (len <= getRtpInfo().getMaxSize()) { //signal-nalu - RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, len, is_mark, pts), gop_pos); + RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackVideo, ptr, len, is_mark, pts), gop_pos); } else { //FU-A模式 packRtpFu(ptr, len, pts, is_mark, gop_pos); diff --git a/src/Extension/H265Rtp.h b/ext-codec/H265Rtp.h similarity index 70% rename from src/Extension/H265Rtp.h rename to ext-codec/H265Rtp.h index 569d8091..1a1c4a8b 100644 --- a/src/Extension/H265Rtp.h +++ b/ext-codec/H265Rtp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,12 +11,12 @@ #ifndef ZLMEDIAKIT_H265RTPCODEC_H #define ZLMEDIAKIT_H265RTPCODEC_H +#include "H265.h" #include "Rtsp/RtpCodec.h" -#include "Extension/H265.h" // for DtsGenerator #include "Common/Stamp.h" -namespace mediakit{ +namespace mediakit { /** * h265 rtp解码类 @@ -28,7 +28,6 @@ public: using Ptr = std::shared_ptr; H265RtpDecoder(); - ~H265RtpDecoder() {} /** * 输入265 rtp包 @@ -37,10 +36,6 @@ public: */ bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override; - CodecId getCodecId() const override{ - return CodecH265; - } - private: bool unpackAp(const RtpPacket::Ptr &rtp, const uint8_t *ptr, ssize_t size, uint64_t stamp); bool mergeFu(const RtpPacket::Ptr &rtp, const uint8_t *ptr, ssize_t size, uint64_t stamp, uint16_t seq); @@ -63,24 +58,10 @@ private: /** * 265 rtp打包类 */ -class H265RtpEncoder : public H265RtpDecoder ,public RtpInfo{ +class H265RtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr; - /** - * @param ui32Ssrc ssrc - * @param ui32MtuSize mtu大小 - * @param ui32SampleRate 采样率,强制为90000 - * @param ui8PayloadType pt类型 - * @param ui8Interleaved rtsp interleaved - */ - H265RtpEncoder(uint32_t ui32Ssrc, - uint32_t ui32MtuSize = 1400, - uint32_t ui32SampleRate = 90000, - uint8_t ui8PayloadType = 96, - uint8_t ui8Interleaved = TrackVideo * 2); - ~H265RtpEncoder() {} - /** * 输入265帧 * @param frame 帧数据,必须 diff --git a/ext-codec/JPEG.cpp b/ext-codec/JPEG.cpp new file mode 100644 index 00000000..df9964f3 --- /dev/null +++ b/ext-codec/JPEG.cpp @@ -0,0 +1,101 @@ +#include "JPEG.h" +#include "JPEGRtp.h" +#include "Rtsp/Rtsp.h" +#include "Util/util.h" +#include "Extension/Factory.h" + +using namespace toolkit; + +namespace mediakit { + +bool JPEGTrack::inputFrame(const Frame::Ptr &frame) { + if (!ready()) { + if (_height > 0 && _width > 0) { + if (_tmp == 0) _tmp = frame->dts(); + else _fps = 1000.0 / (frame->dts() - _tmp); + } else getVideoResolution((uint8_t*)frame->data(), frame->size()); + return false; + } + return VideoTrack::inputFrame(frame); +} + +void JPEGTrack::getVideoResolution(const uint8_t *buf, int len) { + for (int i = 0; i < len - 8; i++) { + if (buf[i] != 0xff) + continue; + if (buf[i + 1] == 0xC0 /*SOF0*/) { + _height = buf[i + 5] * 256 + buf[i + 6]; + _width = buf[i + 7] * 256 + buf[i + 8]; + return; + } + } +} + +class JPEGSdp : public Sdp { +public: + JPEGSdp(int bitrate) : Sdp(90000, Rtsp::PT_JPEG) { + _printer << "m=video 0 RTP/AVP " << (int)getPayloadType() << "\r\n"; + if (bitrate) { + _printer << "b=AS:" << bitrate << "\r\n"; + } + } + + std::string getSdp() const { return _printer; } + +private: + _StrPrinter _printer; +}; + +Sdp::Ptr JPEGTrack::getSdp(uint8_t) const { + return std::make_shared(getBitRate() / 1024); +} + + +namespace { + +CodecId getCodec() { + return CodecJPEG; +} + +Track::Ptr getTrackByCodecId(int sample_rate, int channels, int sample_bit) { + return std::make_shared(); +} + +Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpEncoderByCodecId(uint8_t pt) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpDecoderByCodecId() { + return std::make_shared(); +} + +RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track) { + WarnL << "Unsupported jpeg rtmp encoder"; + return nullptr; +} + +RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track) { + WarnL << "Unsupported jpeg rtmp decoder"; + return nullptr; +} + +Frame::Ptr getFrameFromPtr(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return std::make_shared>(0, CodecJPEG, (char *)data, bytes, dts, pts); +} + +} // namespace + +CodecPlugin jpeg_plugin = { getCodec, + getTrackByCodecId, + getTrackBySdp, + getRtpEncoderByCodecId, + getRtpDecoderByCodecId, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtr }; + +} // namespace mediakit diff --git a/src/Extension/JPEG.h b/ext-codec/JPEG.h similarity index 54% rename from src/Extension/JPEG.h rename to ext-codec/JPEG.h index 016c6620..175699ce 100644 --- a/src/Extension/JPEG.h +++ b/ext-codec/JPEG.h @@ -1,8 +1,8 @@ #ifndef ZLMEDIAKIT_JPEG_H #define ZLMEDIAKIT_JPEG_H -#include "Frame.h" -#include "Track.h" +#include "Extension/Frame.h" +#include "Extension/Track.h" namespace mediakit { @@ -14,12 +14,12 @@ public: int getVideoHeight() const override { return _height; } int getVideoWidth() const override { return _width; } float getVideoFps() const override { return _fps; } - bool ready() override { return _fps > 0; } + bool ready() const override { return _fps > 0; } bool inputFrame(const Frame::Ptr &frame) override; private: - Sdp::Ptr getSdp() override; - Track::Ptr clone() override { return std::make_shared::type>(*this); } + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override { return std::make_shared(*this); } void getVideoResolution(const uint8_t *buf, int len); private: @@ -29,39 +29,34 @@ private: uint64_t _tmp = 0; }; -class JPEGFrame : public Frame { +class JPEGFrameType { public: + virtual ~JPEGFrameType() = default; + virtual uint8_t pixType() const = 0; +}; + +template +class JPEGFrame : public Parent, public JPEGFrameType { +public: + static constexpr auto kJFIFSize = 20u; /** * JPEG/MJPEG帧 - * @param buffer 帧数据 - * @param dts 时间戳,单位毫秒 * @param pix_type pixel format type; AV_PIX_FMT_YUVJ422P || (AVCOL_RANGE_JPEG && AV_PIX_FMT_YUV422P) : 1; AV_PIX_FMT_YUVJ420P || (AVCOL_RANGE_JPEG && AV_PIX_FMT_YUV420P) : 0 - * @param prefix_size JFIF头大小 */ - JPEGFrame(toolkit::Buffer::Ptr buffer, uint64_t dts, uint8_t pix_type = 0, size_t prefix_size = 0) { - _buffer = std::move(buffer); - _dts = dts; + template + JPEGFrame(uint8_t pix_type, ARGS &&...args) : Parent(std::forward(args)...) { _pix_type = pix_type; - _prefix_size = prefix_size; + // JFIF头固定20个字节长度 + CHECK(this->size() > kJFIFSize); } - ~JPEGFrame() override = default; - - uint64_t dts() const override { return _dts; } - size_t prefixSize() const override { return _prefix_size; } + size_t prefixSize() const override { return 0; } bool keyFrame() const override { return true; } bool configFrame() const override { return false; } CodecId getCodecId() const override { return CodecJPEG; } - - char *data() const override { return _buffer->data(); } - size_t size() const override { return _buffer->size(); } - - uint8_t pixType() const {return _pix_type; } + uint8_t pixType() const override { return _pix_type; } private: uint8_t _pix_type; - size_t _prefix_size; - uint64_t _dts; - toolkit::Buffer::Ptr _buffer; }; }//namespace mediakit diff --git a/src/Extension/JPEGRtp.cpp b/ext-codec/JPEGRtp.cpp similarity index 97% rename from src/Extension/JPEGRtp.cpp rename to ext-codec/JPEGRtp.cpp index 384f8296..7d1ae084 100644 --- a/src/Extension/JPEGRtp.cpp +++ b/ext-codec/JPEGRtp.cpp @@ -745,10 +745,10 @@ void JPEGRtpEncoder::rtpSendJpeg(const uint8_t *buf, int size, uint64_t pts, uin hdr_size += 4 + 64 * nb_qtables; /* payload max in one packet */ - len = MIN(size, (int)getMaxSize() - hdr_size); + len = MIN(size, (int)getRtpInfo().getMaxSize() - hdr_size); /* marker bit is last packet in frame */ - auto rtp_packet = makeRtp(getTrackType(), nullptr, len + hdr_size, size == len, pts); + auto rtp_packet = getRtpInfo().makeRtp(TrackVideo, nullptr, len + hdr_size, size == len, pts); p = rtp_packet->getPayload(); /* set main header */ @@ -788,9 +788,7 @@ JPEGRtpDecoder::JPEGRtpDecoder() { memset(&_ctx.timestamp, 0, sizeof(_ctx) - offsetof(decltype(_ctx), timestamp)); } -CodecId JPEGRtpDecoder::getCodecId() const { - return CodecJPEG; -} +using JPEGFrameImp = JPEGFrame >; bool JPEGRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool) { auto payload = rtp->getPayload(); @@ -806,8 +804,7 @@ bool JPEGRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool) { uint8_t type; if (0 == jpeg_parse_packet(nullptr, &_ctx, &stamp, payload, size, seq, marker ? RTP_FLAG_MARKER : 0, &type)) { auto buffer = std::make_shared(std::move(_ctx.frame)); - // JFIF头固定20个字节长度 - auto frame = std::make_shared(std::move(buffer), stamp / 90, type, 20); + auto frame = std::make_shared(type, std::move(buffer), stamp / 90, 0); _ctx.frame.clear(); RtpCodec::inputFrame(std::move(frame)); } @@ -817,17 +814,13 @@ bool JPEGRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool) { //////////////////////////////////////////////////////////////////////// -JPEGRtpEncoder::JPEGRtpEncoder( - uint32_t ssrc, uint32_t mtu, uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved) - : RtpInfo(ssrc, mtu, sample_rate, payload_type, interleaved) {} - - bool JPEGRtpEncoder::inputFrame(const Frame::Ptr &frame) { - auto ptr = (uint8_t *)frame->data() + frame->prefixSize(); - auto len = frame->size() - frame->prefixSize(); + // JFIF头固定20个字节长度 + auto ptr = (uint8_t *)frame->data() + frame->prefixSize() + JPEGFrameImp::kJFIFSize; + auto len = frame->size() - frame->prefixSize() - JPEGFrameImp::kJFIFSize; auto pts = frame->pts(); auto type = 1; - auto jpeg = dynamic_pointer_cast(frame); + auto jpeg = dynamic_pointer_cast(frame); if (jpeg) { type = jpeg->pixType(); } diff --git a/src/Extension/JPEGRtp.h b/ext-codec/JPEGRtp.h similarity index 72% rename from src/Extension/JPEGRtp.h rename to ext-codec/JPEGRtp.h index 00b6c47b..e8d5d81c 100644 --- a/src/Extension/JPEGRtp.h +++ b/ext-codec/JPEGRtp.h @@ -1,10 +1,10 @@ #ifndef ZLMEDIAKIT_JPEGRTP_H #define ZLMEDIAKIT_JPEGRTP_H -#include "Frame.h" #include "Rtsp/RtpCodec.h" +#include "Extension/Frame.h" -namespace mediakit{ +namespace mediakit { /** * RTP/JPEG specific private data. @@ -25,12 +25,6 @@ public: typedef std::shared_ptr Ptr; JPEGRtpDecoder(); - ~JPEGRtpDecoder() override = default; - - /** - * 返回编码类型ID - */ - CodecId getCodecId() const override; /** * 输入rtp并解码 @@ -43,13 +37,10 @@ private: struct PayloadContext _ctx; }; -class JPEGRtpEncoder : public JPEGRtpDecoder, public RtpInfo { +class JPEGRtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr; - JPEGRtpEncoder(uint32_t ssrc, uint32_t mtu = 1400, uint32_t sample_rate = 90000, uint8_t payload_type = 96, uint8_t interleaved = TrackVideo * 2); - ~JPEGRtpEncoder() = default; - bool inputFrame(const Frame::Ptr &frame) override; private: diff --git a/ext-codec/L16.cpp b/ext-codec/L16.cpp new file mode 100644 index 00000000..e38cc081 --- /dev/null +++ b/ext-codec/L16.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#include "L16.h" +#include "Extension/Factory.h" +#include "Extension/CommonRtp.h" +#include "Extension/CommonRtmp.h" + +using namespace std; +using namespace toolkit; + +namespace mediakit { + +/** + * L16类型SDP + */ +class L16Sdp : public Sdp { +public: + /** + * L16采样位数固定为16位 + * @param payload_type rtp payload type + * @param channels 通道数 + * @param sample_rate 音频采样率 + * @param bitrate 比特率 + */ + L16Sdp(int payload_type, int sample_rate, int channels, int bitrate) : Sdp(sample_rate, payload_type) { + _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; + if (bitrate) { + _printer << "b=AS:" << bitrate << "\r\n"; + } + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecL16) << "/" << sample_rate << "/" << channels << "\r\n"; + } + + string getSdp() const override { return _printer; } + +private: + _StrPrinter _printer; +}; + +Sdp::Ptr L16Track::getSdp(uint8_t payload_type) const { + WarnL << "Enter L16Track::getSdp function"; + if (!ready()) { + WarnL << getCodecName() << " Track未准备好"; + return nullptr; + } + return std::make_shared(payload_type, getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); +} + +Track::Ptr L16Track::clone() const { + return std::make_shared(*this); +} + +namespace { + +CodecId getCodec() { + return CodecL16; +} + +Track::Ptr getTrackByCodecId(int sample_rate, int channels, int sample_bit) { + return std::make_shared(sample_rate, channels); +} + +Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track) { + return std::make_shared(track->_samplerate, track->_channel); +} + +RtpCodec::Ptr getRtpEncoderByCodecId(uint8_t pt) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpDecoderByCodecId() { + return std::make_shared(CodecL16); +} + +RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track) { + WarnL << "Unsupported L16 rtmp encoder"; + return nullptr; +} + +RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track) { + WarnL << "Unsupported L16 rtmp decoder"; + return nullptr; +} + +Frame::Ptr getFrameFromPtr(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return std::make_shared(CodecL16, (char *)data, bytes, dts, pts); +} + +} // namespace + +CodecPlugin l16_plugin = { getCodec, + getTrackByCodecId, + getTrackBySdp, + getRtpEncoderByCodecId, + getRtpDecoderByCodecId, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtr }; + +}//namespace mediakit + + diff --git a/src/Extension/L16.h b/ext-codec/L16.h similarity index 53% rename from src/Extension/L16.h rename to ext-codec/L16.h index ca58ab8f..172fccdb 100644 --- a/src/Extension/L16.h +++ b/ext-codec/L16.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,10 +11,10 @@ #ifndef ZLMEDIAKIT_L16_H #define ZLMEDIAKIT_L16_H -#include "Frame.h" -#include "Track.h" +#include "Extension/Frame.h" +#include "Extension/Track.h" -namespace mediakit{ +namespace mediakit { /** * L16音频通道 @@ -25,8 +25,8 @@ public: L16Track(int sample_rate, int channels) : AudioTrackImp(CodecL16,sample_rate,channels,16){} private: - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; }; }//namespace mediakit diff --git a/ext-codec/Opus.cpp b/ext-codec/Opus.cpp new file mode 100644 index 00000000..9fc116c8 --- /dev/null +++ b/ext-codec/Opus.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). + * + * Use of this source code is governed by MIT-like license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#include "Opus.h" +#include "Extension/Factory.h" +#include "Extension/CommonRtp.h" +#include "Extension/CommonRtmp.h" + +using namespace std; +using namespace toolkit; + +namespace mediakit { + +/** + * Opus类型SDP + */ +class OpusSdp : public Sdp { +public: + /** + * 构造opus sdp + * @param payload_type rtp payload type + * @param sample_rate 音频采样率 + * @param channels 通道数 + * @param bitrate 比特率 + */ + OpusSdp(int payload_type, int sample_rate, int channels, int bitrate) : Sdp(sample_rate, payload_type) { + _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; + if (bitrate) { + _printer << "b=AS:" << bitrate << "\r\n"; + } + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecOpus) << "/" << sample_rate << "/" << channels << "\r\n"; + } + + string getSdp() const override { + return _printer; + } + +private: + _StrPrinter _printer; +}; + +Sdp::Ptr OpusTrack::getSdp(uint8_t payload_type) const { + if (!ready()) { + WarnL << getCodecName() << " Track未准备好"; + return nullptr; + } + return std::make_shared(payload_type, getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); +} + +namespace { + +CodecId getCodec() { + return CodecOpus; +} + +Track::Ptr getTrackByCodecId(int sample_rate, int channels, int sample_bit) { + return std::make_shared(); +} + +Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpEncoderByCodecId(uint8_t pt) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpDecoderByCodecId() { + return std::make_shared(CodecOpus); +} + +RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +Frame::Ptr getFrameFromPtr(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return std::make_shared(CodecOpus, (char *)data, bytes, dts, pts); +} + +} // namespace + +CodecPlugin opus_plugin = { getCodec, + getTrackByCodecId, + getTrackBySdp, + getRtpEncoderByCodecId, + getRtpDecoderByCodecId, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtr }; + +}//namespace mediakit \ No newline at end of file diff --git a/src/Extension/Opus.h b/ext-codec/Opus.h similarity index 51% rename from src/Extension/Opus.h rename to ext-codec/Opus.h index 08dea847..e154b36e 100644 --- a/src/Extension/Opus.h +++ b/ext-codec/Opus.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,10 +11,10 @@ #ifndef ZLMEDIAKIT_OPUS_H #define ZLMEDIAKIT_OPUS_H -#include "Frame.h" -#include "Track.h" +#include "Extension/Frame.h" +#include "Extension/Track.h" -namespace mediakit{ +namespace mediakit { /** * Opus帧音频通道 @@ -26,11 +26,11 @@ public: private: //克隆该Track - Track::Ptr clone() override { - return std::make_shared::type >(*this); + Track::Ptr clone() const override { + return std::make_shared(*this); } //生成sdp - Sdp::Ptr getSdp() override ; + Sdp::Ptr getSdp(uint8_t payload_type) const override ; }; }//namespace mediakit diff --git a/src/Extension/SPSParser.c b/ext-codec/SPSParser.c similarity index 100% rename from src/Extension/SPSParser.c rename to ext-codec/SPSParser.c diff --git a/src/Extension/SPSParser.h b/ext-codec/SPSParser.h similarity index 100% rename from src/Extension/SPSParser.h rename to ext-codec/SPSParser.h diff --git a/package/rpm/ZLMediaKit.spec b/package/rpm/ZLMediaKit.spec index f62742f6..9ff902d6 100644 --- a/package/rpm/ZLMediaKit.spec +++ b/package/rpm/ZLMediaKit.spec @@ -24,7 +24,7 @@ Summary: A lightweight, high performance and stable stream server and client fra Group: development License: MIT -URL: https://github.com/xia-chu/ZLMediaKit +URL: https://github.com/ZLMediaKit/ZLMediaKit Source0: %{name}-%{version}.tar.xz %if %{with openssl} diff --git a/player/AudioSRC.cpp b/player/AudioSRC.cpp index a1a58b44..5fb7aa0e 100644 --- a/player/AudioSRC.cpp +++ b/player/AudioSRC.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/player/AudioSRC.h b/player/AudioSRC.h index 5cd3e6d3..db60d379 100644 --- a/player/AudioSRC.h +++ b/player/AudioSRC.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/player/SDLAudioDevice.cpp b/player/SDLAudioDevice.cpp index 76093c89..14f74add 100644 --- a/player/SDLAudioDevice.cpp +++ b/player/SDLAudioDevice.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/player/SDLAudioDevice.h b/player/SDLAudioDevice.h index 901c638b..bddea9cb 100644 --- a/player/SDLAudioDevice.h +++ b/player/SDLAudioDevice.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/player/YuvDisplayer.h b/player/YuvDisplayer.h index d2defc74..54702cec 100644 --- a/player/YuvDisplayer.h +++ b/player/YuvDisplayer.h @@ -1,9 +1,9 @@  /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/player/test_player.cpp b/player/test_player.cpp index faf29af7..79102a94 100644 --- a/player/test_player.cpp +++ b/player/test_player.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/postman/ZLMediaKit.postman_collection.json b/postman/ZLMediaKit.postman_collection.json index b8bbd0f7..1111850f 100644 --- a/postman/ZLMediaKit.postman_collection.json +++ b/postman/ZLMediaKit.postman_collection.json @@ -2184,6 +2184,38 @@ } }, "response": [] + }, + { + "name": "下载文件(downloadFile)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{ZLMediaKit_URL}}/index/api/downloadFile?file_path=/path/to/file.ext", + "host": [ + "{{ZLMediaKit_URL}}" + ], + "path": [ + "index", + "api", + "downloadFile" + ], + "query": [ + { + "key": "file_path", + "value": "/path/to/file.ext", + "description": "文件绝对路径,根据文件名生成Content-Type;该接口将触发on_http_access hook" + }, + { + "key": "save_name", + "value": "test", + "description": "浏览器下载文件后保存文件名;可选参数", + "disabled": true + } + ] + } + }, + "response": [] } ], "event": [ diff --git a/server/FFmpegSource.cpp b/server/FFmpegSource.cpp index 8363950c..511a7e56 100644 --- a/server/FFmpegSource.cpp +++ b/server/FFmpegSource.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -343,7 +343,7 @@ void FFmpegSnap::makeSnap(const string &play_url, const string &save_path, float // FFmpeg进程退出了可以取消定时器了 delayTask->cancel(); // 执行回调函数 - bool success = process->exit_code() == 0 && File::fileSize(save_path.data()); - cb(success, (!success && !log_file.empty()) ? File::loadFile(log_file.data()) : ""); + bool success = process->exit_code() == 0 && File::fileSize(save_path); + cb(success, (!success && !log_file.empty()) ? File::loadFile(log_file) : ""); }); } diff --git a/server/FFmpegSource.h b/server/FFmpegSource.h index 8efb7ced..067e2e83 100644 --- a/server/FFmpegSource.h +++ b/server/FFmpegSource.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/server/Process.cpp b/server/Process.cpp index 140282d9..d2b02abc 100644 --- a/server/Process.cpp +++ b/server/Process.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -65,7 +65,7 @@ static int runChildProcess(string cmd, string log_file) { } //重定向shell日志至文件 - auto fp = File::create_file(log_file.data(), "ab"); + auto fp = File::create_file(log_file, "ab"); if (!fp) { fprintf(stderr, "open log file %s failed:%d(%s)\r\n", log_file.data(), get_uv_error(), get_uv_errmsg()); } else { @@ -121,7 +121,7 @@ void Process::run(const string &cmd, string log_file) { } //重定向shell日志至文件 - auto fp = File::create_file(log_file.data(), "ab"); + auto fp = File::create_file(log_file, "ab"); if (!fp) { fprintf(stderr, "open log file %s failed:%d(%s)\r\n", log_file.data(), get_uv_error(), get_uv_errmsg()); } else { @@ -157,12 +157,12 @@ void Process::run(const string &cmd, string log_file) { WarnL << "clone process failed:" << get_uv_errmsg(); free(_process_stack); _process_stack = nullptr; - throw std::runtime_error(StrPrinter << "fork child process failed,err:" << get_uv_errmsg()); + throw std::runtime_error(StrPrinter << "clone child process failed, cmd: " << cmd << ",err:" << get_uv_errmsg()); } #else _pid = fork(); if (_pid == -1) { - throw std::runtime_error(StrPrinter << "fork child process failed,err:" << get_uv_errmsg()); + throw std::runtime_error(StrPrinter << "fork child process failed, cmd: " << cmd << ",err:" << get_uv_errmsg()); } if (_pid == 0) { //子进程 diff --git a/server/Process.h b/server/Process.h index 06f55345..f4befaeb 100644 --- a/server/Process.h +++ b/server/Process.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/server/System.cpp b/server/System.cpp index c06d34e1..77578924 100644 --- a/server/System.cpp +++ b/server/System.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/server/System.h b/server/System.h index 9ca6fda0..bc380d5b 100644 --- a/server/System.h +++ b/server/System.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 8bd2f416..44da3e5c 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -72,18 +72,20 @@ const string kApiDebug = API_FIELD"apiDebug"; const string kSecret = API_FIELD"secret"; const string kSnapRoot = API_FIELD"snapRoot"; const string kDefaultSnap = API_FIELD"defaultSnap"; +const string kDownloadRoot = API_FIELD"downloadRoot"; static onceToken token([]() { mINI::Instance()[kApiDebug] = "1"; mINI::Instance()[kSecret] = "035c73f7-bb6b-4889-a715-d9eb2d1925cc"; mINI::Instance()[kSnapRoot] = "./www/snap/"; mINI::Instance()[kDefaultSnap] = "./www/logo.png"; + mINI::Instance()[kDownloadRoot] = "./www"; }); }//namespace API using HttpApi = function; //http api列表 -static map s_map_api; +static map s_map_api; static void responseApi(const Json::Value &res, const HttpSession::HttpResponseInvoker &invoker){ GET_CONFIG(string, charSet, Http::kCharSet); @@ -540,7 +542,7 @@ void getStatisticJson(const function &cb) { } void addStreamProxy(const string &vhost, const string &app, const string &stream, const string &url, int retry_count, - const ProtocolOption &option, int rtp_type, float timeout_sec, + const ProtocolOption &option, int rtp_type, float timeout_sec, const mINI &args, const function &cb) { auto key = getProxyKey(vhost, app, stream); lock_guard lck(s_proxyMapMtx); @@ -553,6 +555,9 @@ void addStreamProxy(const string &vhost, const string &app, const string &stream auto player = std::make_shared(vhost, app, stream, option, retry_count); s_proxyMap[key] = player; + // 先透传参数 + player->mINI::operator=(args); + //指定RTP over TCP(播放rtsp时有效) (*player)[Client::kRtpType] = rtp_type; @@ -718,7 +723,7 @@ void installWebApi() { return 0; }); - val["msg"] = "服务器将在一秒后自动重启"; + val["msg"] = "MediaServer will reboot in on 1 second"; }); #else //增加Windows下的重启代码 @@ -1058,6 +1063,11 @@ void installWebApi() { CHECK_SECRET(); CHECK_ARGS("vhost","app","stream","url"); + mINI args; + for (auto &pr : allArgs.getArgs()) { + args.emplace(pr.first, pr.second); + } + ProtocolOption option(allArgs); auto retry_count = allArgs["retry_count"].empty()? -1: allArgs["retry_count"].as(); addStreamProxy(allArgs["vhost"], @@ -1068,6 +1078,7 @@ void installWebApi() { option, allArgs["rtp_type"], allArgs["timeout_sec"], + args, [invoker,val,headerOut](const SockException &ex,const string &key) mutable{ if (ex) { val["code"] = API::OtherFailed; @@ -1529,18 +1540,35 @@ void installWebApi() { if (!name.empty()) { record_path += name; } - int result = File::delete_file(record_path.data()); - if (result) { - // 不等于0时代表失败 - record_path = "delete error"; + bool recording = false; + { + auto src = MediaSource::find(allArgs["vhost"], allArgs["app"], allArgs["stream"]); + if (src && src->isRecording(Recorder::type_mp4)) { + recording = true; + } } val["path"] = record_path; - val["code"] = result; + if (!recording) { + val["code"] = File::delete_file(record_path, true); + return; + } + File::scanDir(record_path, [](const string &path, bool is_dir) { + if (is_dir) { + return true; + } + if (path.find("/.") == std::string::npos) { + File::delete_file(path); + } else { + TraceL << "Ignore tmp mp4 file: " << path; + } + return true; + }, true, true); + File::deleteEmptyDir(record_path); }); //获取录像文件夹列表或mp4文件列表 - //http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01 - api_regist("/index/api/getMp4RecordFile", [](API_ARGS_MAP){ + //http://127.0.0.1/index/api/getMP4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01 + api_regist("/index/api/getMP4RecordFile", [](API_ARGS_MAP){ CHECK_SECRET(); CHECK_ARGS("vhost", "app", "stream"); auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"]}; @@ -1583,7 +1611,7 @@ void installWebApi() { static bool s_snap_success_once = false; StrCaseMap headerOut; GET_CONFIG(string, defaultSnap, API::kDefaultSnap); - if (!File::fileSize(snap_path.data())) { + if (!File::fileSize(snap_path)) { if (!err_msg.empty() && (!s_snap_success_once || defaultSnap.empty())) { //重来没截图成功过或者默认截图图片为空,那么直接返回FFmpeg错误日志 headerOut["Content-Type"] = HttpFileManager::getContentType(".txt"); @@ -1645,7 +1673,7 @@ void installWebApi() { if (!have_old_snap) { //无过期截图,生成一个空文件,目的是顺便创建文件夹路径 //同时防止在FFmpeg生成截图途中不停的尝试调用该api多次启动FFmpeg进程 - auto file = File::create_file(new_snap.data(), "wb"); + auto file = File::create_file(new_snap, "wb"); if (file) { fclose(file); } @@ -1656,10 +1684,10 @@ void installWebApi() { FFmpegSnap::makeSnap(allArgs["url"], new_snap_tmp, allArgs["timeout_sec"], [invoker, allArgs, new_snap, new_snap_tmp](bool success, const string &err_msg) { if (!success) { //生成截图失败,可能残留空文件 - File::delete_file(new_snap_tmp.data()); + File::delete_file(new_snap_tmp); } else { //临时文件改成正式文件 - File::delete_file(new_snap.data()); + File::delete_file(new_snap); rename(new_snap_tmp.data(), new_snap.data()); } responseSnap(new_snap, allArgs.getParser().getHeader(), invoker, err_msg); @@ -1694,7 +1722,7 @@ void installWebApi() { auto &allArgs = _args; CHECK_ARGS("app", "stream"); - return StrPrinter << RTC_SCHEMA << "://" << _args["Host"] << "/" << _args["app"] << "/" + return StrPrinter << "rtc://" << _args["Host"] << "/" << _args["app"] << "/" << _args["stream"] << "?" << _args.getParser().params() + "&session=" + _session_id; } @@ -1709,8 +1737,8 @@ void installWebApi() { auto offer = allArgs.getArgs(); CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty"); - WebRtcPluginManager::Instance().getAnswerSdp(static_cast(sender), type, - WebRtcArgsImp(allArgs, sender.getIdentifier()), + auto args = std::make_shared(allArgs, sender.getIdentifier()); + WebRtcPluginManager::Instance().getAnswerSdp(static_cast(sender), type, *args, [invoker, val, offer, headerOut](const WebRtcInterface &exchanger) mutable { //设置返回类型 headerOut["Content-Type"] = HttpFileManager::getContentType(".json"); @@ -1737,7 +1765,8 @@ void installWebApi() { auto &session = static_cast(sender); auto location = std::string("http") + (session.overSsl() ? "s" : "") + "://" + allArgs["host"] + delete_webrtc_url; - WebRtcPluginManager::Instance().getAnswerSdp(session, type, WebRtcArgsImp(allArgs, sender.getIdentifier()), + auto args = std::make_shared(allArgs, sender.getIdentifier()); + WebRtcPluginManager::Instance().getAnswerSdp(session, type, *args, [invoker, offer, headerOut, location](const WebRtcInterface &exchanger) mutable { // 设置跨域 headerOut["Access-Control-Allow-Origin"] = "*"; @@ -1790,6 +1819,8 @@ void installWebApi() { CHECK_ARGS("vhost", "app", "stream", "file_path"); ProtocolOption option; + // mp4支持多track + option.max_track = 16; // 默认解复用mp4不生成mp4 option.enable_mp4 = false; // 但是如果参数明确指定开启mp4, 那么也允许之 @@ -1802,159 +1833,55 @@ void installWebApi() { reader->startReadMP4(0, true, allArgs["file_repeat"]); }); - ////////////以下是注册的Hook API//////////// - api_regist("/index/hook/on_publish",[](API_ARGS_JSON){ - //开始推流事件 - //转换hls - val["enable_hls"] = true; - //不录制mp4 - val["enable_mp4"] = false; + GET_CONFIG_FUNC(std::set, download_roots, API::kDownloadRoot, [](const string &str) -> std::set { + std::set ret; + auto vec = toolkit::split(str, ";"); + for (auto &item : vec) { + auto root = File::absolutePath(item, "", true); + ret.emplace(std::move(root)); + } + return ret; }); - api_regist("/index/hook/on_play",[](API_ARGS_JSON){ - //开始播放事件 - }); + api_regist("/index/api/downloadFile", [](API_ARGS_MAP_ASYNC) { + CHECK_ARGS("file_path"); + auto file_path = allArgs["file_path"]; - api_regist("/index/hook/on_flow_report",[](API_ARGS_JSON){ - //流量统计hook api - }); - - api_regist("/index/hook/on_rtsp_realm",[](API_ARGS_JSON){ - //rtsp是否需要鉴权,默认需要鉴权 - val["code"] = API::Success; - val["realm"] = "zlmediakit_reaml"; - }); - - api_regist("/index/hook/on_rtsp_auth",[](API_ARGS_JSON){ - //rtsp鉴权密码,密码等于用户名 - //rtsp可以有双重鉴权!后面还会触发on_play事件 - CHECK_ARGS("user_name"); - val["code"] = API::Success; - val["encrypted"] = false; - val["passwd"] = allArgs["user_name"].data(); - }); - - api_regist("/index/hook/on_stream_changed",[](API_ARGS_JSON){ - //媒体注册或反注册事件 - }); - - -#if !defined(_WIN32) - api_regist("/index/hook/on_stream_not_found_ffmpeg",[](API_ARGS_MAP_ASYNC){ - //媒体未找到事件,我们都及时拉流hks作为替代品,目的是为了测试按需拉流 - CHECK_SECRET(); - CHECK_ARGS("vhost","app","stream"); - //通过FFmpeg按需拉流 - GET_CONFIG(int,rtmp_port,Rtmp::kPort); - GET_CONFIG(int,timeout_sec,Hook::kTimeoutSec); - - string dst_url = StrPrinter - << "rtmp://127.0.0.1:" - << rtmp_port << "/" - << allArgs["app"] << "/" - << allArgs["stream"] << "?vhost=" - << allArgs["vhost"]; - - addFFmpegSource("", "http://hls-ott-zhibo.wasu.tv/live/272/index.m3u8",/** ffmpeg拉流支持任意编码格式任意协议 **/ - dst_url, - (1000 * timeout_sec) - 500, - false, - false, - [invoker,val,headerOut](const SockException &ex,const string &key) mutable{ - if(ex){ - val["code"] = API::OtherFailed; - val["msg"] = ex.what(); - }else{ - val["data"]["key"] = key; - } - invoker(200, headerOut, val.toStyledString()); - }); - }); -#endif//!defined(_WIN32) - - api_regist("/index/hook/on_stream_not_found",[](API_ARGS_MAP_ASYNC){ - //媒体未找到事件,我们都及时拉流hks作为替代品,目的是为了测试按需拉流 - CHECK_SECRET(); - CHECK_ARGS("vhost","app","stream", "schema"); - - ProtocolOption option; - option.enable_hls = allArgs["schema"] == HLS_SCHEMA; - option.enable_mp4 = false; - - //通过内置支持的rtsp/rtmp按需拉流 - addStreamProxy(allArgs["vhost"], - allArgs["app"], - allArgs["stream"], - /** 支持rtsp和rtmp方式拉流 ,rtsp支持h265/h264/aac,rtmp仅支持h264/aac **/ - "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov", - -1,/*无限重试*/ - option, - 0,//rtp over tcp方式拉流 - 10,//10秒超时 - [invoker,val,headerOut](const SockException &ex,const string &key) mutable{ - if(ex){ - val["code"] = API::OtherFailed; - val["msg"] = ex.what(); - }else{ - val["data"]["key"] = key; - } - invoker(200, headerOut, val.toStyledString()); - }); - }); - - api_regist("/index/hook/on_record_mp4",[](API_ARGS_JSON){ - //录制mp4分片完毕事件 - }); - - api_regist("/index/hook/on_shell_login",[](API_ARGS_JSON){ - //shell登录调试事件 - }); - - api_regist("/index/hook/on_stream_none_reader",[](API_ARGS_JSON){ - //无人观看流默认关闭 - val["close"] = true; - }); - - api_regist("/index/hook/on_send_rtp_stopped",[](API_ARGS_JSON){ - //发送rtp(startSendRtp)被动关闭时回调 - }); - - static auto checkAccess = [](const string ¶ms){ - //我们假定大家都要权限访问 - return true; - }; - - api_regist("/index/hook/on_http_access",[](API_ARGS_MAP){ - //在这里根据allArgs["params"](url参数)来判断该http客户端是否有权限访问该文件 - if(!checkAccess(allArgs["params"])){ - //无访问权限 - val["err"] = "无访问权限"; - //仅限制访问当前目录 - val["path"] = ""; - //标记该客户端无权限1分钟 - val["second"] = 60; + if (file_path.find("..") != std::string::npos) { + invoker(401, StrCaseMap{}, "You can not access parent directory"); + return; + } + bool safe = false; + for (auto &root : download_roots) { + if (start_with(file_path, root)) { + safe = true; + break; + } + } + if (!safe) { + invoker(401, StrCaseMap{}, "You can not download files outside the root directory"); return; } - //可以访问 - val["err"] = ""; - //只能访问当前目录 - val["path"] = ""; - //该http客户端用户被授予10分钟的访问权限,该权限仅限访问当前目录 - val["second"] = 10 * 60; - }); + // 通过on_http_access完成文件下载鉴权,请务必确认访问鉴权url参数以及访问文件路径是否合法 + HttpSession::HttpAccessPathInvoker file_invoker = [allArgs, invoker](const string &err_msg, const string &cookie_path_in, int life_second) mutable { + if (!err_msg.empty()) { + invoker(401, StrCaseMap{}, err_msg); + } else { + StrCaseMap res_header; + auto save_name = allArgs["save_name"]; + if (!save_name.empty()) { + res_header.emplace("Content-Disposition", "attachment;filename=\"" + save_name + "\""); + } + invoker.responseFile(allArgs.getParser().getHeader(), res_header, allArgs["file_path"]); + } + }; - api_regist("/index/hook/on_server_started",[](API_ARGS_JSON){ - //服务器重启报告 - }); - - api_regist("/index/hook/on_server_keepalive",[](API_ARGS_JSON){ - //心跳hook - }); - - api_regist("/index/hook/on_rtp_server_timeout",[](API_ARGS_JSON){ - //rtp server 超时 - TraceL <; @@ -155,8 +151,6 @@ public: } } - ~HttpAllArgs() = default; - template toolkit::variant operator[](const Key &key) const { return (toolkit::variant)_get_value(*(HttpAllArgs*)this, key); @@ -218,7 +212,7 @@ bool checkArgs(Args &args, const First &first, const KeyTypes &...keys) { //检查http url中或body中或http header参数是否为空的宏 #define CHECK_ARGS(...) \ if(!checkArgs(allArgs,##__VA_ARGS__)){ \ - throw InvalidArgsException("缺少必要参数:" #__VA_ARGS__); \ + throw InvalidArgsException("Required parameter missed: " #__VA_ARGS__); \ } // 检查http参数中是否附带secret密钥的宏,127.0.0.1的ip不检查密钥 @@ -231,7 +225,7 @@ bool checkArgs(Args &args, const First &first, const KeyTypes &...keys) { } \ CHECK_ARGS("secret"); \ if (api_secret != allArgs["secret"]) { \ - throw AuthException("secret错误"); \ + throw AuthException("Incorrect secret"); \ } \ } while(false); @@ -247,6 +241,6 @@ bool closeRtpServer(const std::string &stream_id); Json::Value makeMediaSourceJson(mediakit::MediaSource &media); void getStatisticJson(const std::function &cb); void addStreamProxy(const std::string &vhost, const std::string &app, const std::string &stream, const std::string &url, int retry_count, - const mediakit::ProtocolOption &option, int rtp_type, float timeout_sec, + const mediakit::ProtocolOption &option, int rtp_type, float timeout_sec, const toolkit::mINI &args, const std::function &cb); #endif //ZLMEDIAKIT_WEBAPI_H diff --git a/server/WebHook.cpp b/server/WebHook.cpp index 409d11f4..aa99a94c 100755 --- a/server/WebHook.cpp +++ b/server/WebHook.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -174,7 +174,7 @@ void do_http_hook(const string &url, const ArgsType &body, const function(body)["mediaServerId"] = mediaServerId; - const_cast(body)["hook_index"] = s_hook_index++; + const_cast(body)["hook_index"] = (Json::UInt64)(s_hook_index++); auto requester = std::make_shared(); requester->setMethod("POST"); @@ -301,7 +301,7 @@ static void pullStreamFromOrigin(const vector &urls, size_t index, size_ option.enable_hls = option.enable_hls || (args.schema == HLS_SCHEMA); option.enable_mp4 = false; - addStreamProxy(args.vhost, args.app, args.stream, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec, [=](const SockException &ex, const string &key) mutable { + addStreamProxy(args.vhost, args.app, args.stream, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec, mINI{}, [=](const SockException &ex, const string &key) mutable { if (!ex) { return; } diff --git a/server/WebHook.h b/server/WebHook.h index c75d05c3..1c952c8c 100755 --- a/server/WebHook.h +++ b/server/WebHook.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/server/main.cpp b/server/main.cpp index 70b6348f..1b2f4b1a 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -203,11 +203,6 @@ public: "日志保存文件夹路径",/*该选项说明文字*/ nullptr); } - - ~CMD_main() override{} - const char *description() const override{ - return "主程序命令参数"; - } }; //全局变量,在WebApi中用于保存配置文件用 @@ -263,14 +258,14 @@ int start_main(int argc,char *argv[]) { //加载配置文件,如果配置文件不存在就创建一个 loadIniConfig(g_ini_file.data()); - if (!File::is_dir(ssl_file.data())) { - //不是文件夹,加载证书,证书包含公钥和私钥 + if (!File::is_dir(ssl_file)) { + // 不是文件夹,加载证书,证书包含公钥和私钥 SSL_Initor::Instance().loadCertificate(ssl_file.data()); } else { //加载文件夹下的所有证书 - File::scanDir(ssl_file, [](const string &path, bool isDir) { + File::scanDir(ssl_file,[](const string &path, bool isDir){ if (!isDir) { - //最后的一个证书会当做默认证书(客户端ssl握手时未指定主机) + // 最后的一个证书会当做默认证书(客户端ssl握手时未指定主机) SSL_Initor::Instance().loadCertificate(path.data()); } return true; @@ -290,6 +285,7 @@ int start_main(int argc,char *argv[]) { //如果需要调用getSnap和addFFmpegSource接口,可以关闭cpu亲和性 EventPollerPool::setPoolSize(threads); + WorkThreadPool::setPoolSize(threads); EventPollerPool::enableCpuAffinity(affinity); //简单的telnet服务器,可用于服务器调试,但是不能使用23端口,否则telnet上了莫名其妙的现象 diff --git a/src/Codec/AACEncoder.cpp b/src/Codec/AACEncoder.cpp index 4a335e03..feb3b350 100644 --- a/src/Codec/AACEncoder.cpp +++ b/src/Codec/AACEncoder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Codec/AACEncoder.h b/src/Codec/AACEncoder.h index b236a66f..657a43b9 100644 --- a/src/Codec/AACEncoder.h +++ b/src/Codec/AACEncoder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Codec/H264Encoder.cpp b/src/Codec/H264Encoder.cpp index 6fe0e3f7..92ac2a39 100644 --- a/src/Codec/H264Encoder.cpp +++ b/src/Codec/H264Encoder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Codec/H264Encoder.h b/src/Codec/H264Encoder.h index a63eb6ad..46c86150 100644 --- a/src/Codec/H264Encoder.h +++ b/src/Codec/H264Encoder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Codec/Transcode.cpp b/src/Codec/Transcode.cpp index 25f9e77c..aaa641fe 100644 --- a/src/Codec/Transcode.cpp +++ b/src/Codec/Transcode.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -15,7 +15,6 @@ #include "Util/File.h" #include "Util/uv_errno.h" #include "Transcode.h" -#include "Extension/AAC.h" #include "Common/config.h" #define MAX_DELAY_SECOND 3 diff --git a/src/Codec/Transcode.h b/src/Codec/Transcode.h index 8c33b711..4cfaee62 100644 --- a/src/Codec/Transcode.h +++ b/src/Codec/Transcode.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -65,7 +65,6 @@ private: class TaskManager { public: - TaskManager() = default; virtual ~TaskManager(); void setMaxTaskSize(size_t size); @@ -84,7 +83,6 @@ private: class ThreadExitException : public std::runtime_error { public: ThreadExitException() : std::runtime_error("exit") {} - ~ThreadExitException() = default; }; private: diff --git a/src/Common/Device.cpp b/src/Common/Device.cpp index 2b1edfab..9b652911 100644 --- a/src/Common/Device.cpp +++ b/src/Common/Device.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,11 +11,7 @@ #include "Device.h" #include "Util/logger.h" #include "Util/base64.h" -#include "Extension/AAC.h" -#include "Extension/Opus.h" -#include "Extension/G711.h" -#include "Extension/H264.h" -#include "Extension/H265.h" +#include "Extension/Factory.h" #ifdef ENABLE_FAAC #include "Codec/AACEncoder.h" #endif //ENABLE_FAAC @@ -85,15 +81,7 @@ bool DevChannel::inputH264(const char *data, int len, uint64_t dts, uint64_t pts pts = dts; } - //由于rtmp/hls/mp4需要缓存时间戳相同的帧, - //所以使用FrameNoCacheAble类型的帧反而会在转换成FrameCacheAble时多次内存拷贝 - //在此处只拷贝一次,性能开销更低 - auto frame = FrameImp::create(); - frame->_dts = dts; - frame->_pts = pts; - frame->_buffer.assign(data, len); - frame->_prefix_size = prefixSize(data,len); - return inputFrame(frame); + return inputFrame(Factory::getFrameFromPtr(CodecH264,data, len, dts, pts)); } bool DevChannel::inputH265(const char *data, int len, uint64_t dts, uint64_t pts) { @@ -104,30 +92,10 @@ bool DevChannel::inputH265(const char *data, int len, uint64_t dts, uint64_t pts pts = dts; } - //由于rtmp/hls/mp4需要缓存时间戳相同的帧, - //所以使用FrameNoCacheAble类型的帧反而会在转换成FrameCacheAble时多次内存拷贝 - //在此处只拷贝一次,性能开销更低 - auto frame = FrameImp::create(); - frame->_dts = dts; - frame->_pts = pts; - frame->_buffer.assign(data, len); - frame->_prefix_size = prefixSize(data,len); - return inputFrame(frame); + return inputFrame(Factory::getFrameFromPtr(CodecH265, data, len, dts, pts)); } -class FrameAutoDelete : public FrameFromPtr{ -public: - template - FrameAutoDelete(ARGS && ...args) : FrameFromPtr(std::forward(args)...){} - - ~FrameAutoDelete() override { - delete [] _ptr; - }; - - bool cacheAble() const override { - return true; - } -}; +#define ADTS_HEADER_LEN 7 bool DevChannel::inputAAC(const char *data_without_adts, int len, uint64_t dts, const char *adts_header){ if (dts == 0) { @@ -136,47 +104,36 @@ bool DevChannel::inputAAC(const char *data_without_adts, int len, uint64_t dts, if (!adts_header) { //没有adts头 - return inputFrame(std::make_shared(_audio->codecId, (char *) data_without_adts, len, dts, 0, 0)); + return inputFrame(std::make_shared(CodecAAC, (char *) data_without_adts, len, dts, 0, 0)); } if (adts_header + ADTS_HEADER_LEN == data_without_adts) { //adts头和帧在一起 - return inputFrame(std::make_shared(_audio->codecId, (char *) data_without_adts - ADTS_HEADER_LEN, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN)); + return inputFrame(std::make_shared(CodecAAC, (char *) data_without_adts - ADTS_HEADER_LEN, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN)); } //adts头和帧不在一起 char *data_with_adts = new char[len + ADTS_HEADER_LEN]; memcpy(data_with_adts, adts_header, ADTS_HEADER_LEN); memcpy(data_with_adts + ADTS_HEADER_LEN, data_without_adts, len); - return inputFrame(std::make_shared(_audio->codecId, data_with_adts, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN)); - + return inputFrame(std::make_shared(CodecAAC, data_with_adts, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN)); } bool DevChannel::inputAudio(const char *data, int len, uint64_t dts){ if (dts == 0) { dts = _aTicker[1].elapsedTime(); } - return inputFrame(std::make_shared(_audio->codecId, (char *) data, len, dts, 0)); + return inputFrame(Factory::getFrameFromPtr(_audio->codecId, (char *) data, len, dts, dts)); } bool DevChannel::initVideo(const VideoInfo &info) { _video = std::make_shared(info); - switch (info.codecId){ - case CodecH265 : return addTrack(std::make_shared()); - case CodecH264 : return addTrack(std::make_shared()); - default: WarnL << "不支持该类型的视频编码类型:" << info.codecId; return false; - } + return addTrack(Factory::getTrackByCodecId(info.codecId)); } bool DevChannel::initAudio(const AudioInfo &info) { _audio = std::make_shared(info); - switch (info.codecId) { - case CodecAAC : return addTrack(std::make_shared()); - case CodecG711A : - case CodecG711U : return addTrack(std::make_shared(info.codecId, info.iSampleRate, info.iChannel, info.iSampleBit)); - case CodecOpus : return addTrack(std::make_shared()); - default: WarnL << "不支持该类型的音频编码类型:" << info.codecId; return false; - } + return addTrack(Factory::getTrackByCodecId(info.codecId, info.iSampleRate, info.iChannel, info.iSampleBit)); } bool DevChannel::inputFrame(const Frame::Ptr &frame) { diff --git a/src/Common/Device.h b/src/Common/Device.h index cb99657d..6af52626 100644 --- a/src/Common/Device.h +++ b/src/Common/Device.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -49,7 +49,6 @@ public: //fDuration<=0为直播,否则为点播 DevChannel(const MediaTuple& tuple, float duration = 0, const ProtocolOption &option = ProtocolOption()) : MultiMediaSourceMuxer(tuple, duration, option) {} - ~DevChannel() override = default; /** * 初始化视频Track diff --git a/src/Common/JemallocUtil.cpp b/src/Common/JemallocUtil.cpp index f5d0d2a7..e19f8b8c 100644 --- a/src/Common/JemallocUtil.cpp +++ b/src/Common/JemallocUtil.cpp @@ -1,9 +1,9 @@ /* -* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. +* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * -* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). +* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * -* Use of this source code is governed by MIT license that can be found in the +* Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Common/JemallocUtil.h b/src/Common/JemallocUtil.h index 71f7722b..b1c1472a 100644 --- a/src/Common/JemallocUtil.h +++ b/src/Common/JemallocUtil.h @@ -1,9 +1,9 @@ /* -* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. +* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * -* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). +* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * -* Use of this source code is governed by MIT license that can be found in the +* Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -16,9 +16,6 @@ namespace mediakit { class JemallocUtil { public: - JemallocUtil() = default; - ~JemallocUtil() = default; - static void enable_profiling(); static void disable_profiling(); diff --git a/src/Common/MediaSink.cpp b/src/Common/MediaSink.cpp index d90d5798..3fc5a9ea 100644 --- a/src/Common/MediaSink.cpp +++ b/src/Common/MediaSink.cpp @@ -1,16 +1,18 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "MediaSink.h" -#include "Extension/AAC.h" #include "Common/config.h" +#include "Extension/Factory.h" + +#define MUTE_AUDIO_INDEX 0xFFFF using namespace std; @@ -33,28 +35,30 @@ bool MediaSink::addTrack(const Track::Ptr &track_in) { WarnL << "All track is ready, add track too late: " << track_in->getCodecName(); return false; } - //克隆Track,只拷贝其数据,不拷贝其数据转发关系 + // 克隆Track,只拷贝其数据,不拷贝其数据转发关系 auto track = track_in->clone(); - auto track_type = track->getTrackType(); - _track_map[track_type] = std::make_pair(track, false); - _track_ready_callback[track_type] = [this, track]() { - onTrackReady(track); - }; + auto index = track->getIndex(); + if (!_track_map.emplace(index, std::make_pair(track, false)).second) { + WarnL << "Already add a same track: " << track->getIndex() << ", codec: " << track->getCodecName(); + return false; + } _ticker.resetTime(); + _audio_add = track->getTrackType() == TrackAudio ? true : _audio_add; + _track_ready_callback[index] = [this, track]() { onTrackReady(track); }; track->addDelegate([this](const Frame::Ptr &frame) { if (_all_track_ready) { return onTrackFrame(frame); } - auto &frame_unread = _frame_unread[frame->getTrackType()]; + auto &frame_unread = _frame_unread[frame->getIndex()]; GET_CONFIG(uint32_t, kMaxUnreadyFrame, General::kUnreadyFrameCache); if (frame_unread.size() > kMaxUnreadyFrame) { - //未就绪的的track,不能缓存太多的帧,否则可能内存溢出 + // 未就绪的的track,不能缓存太多的帧,否则可能内存溢出 frame_unread.clear(); WarnL << "Cached frame of unready track(" << frame->getCodecName() << ") is too much, now cleared"; } - //还有Track未就绪,先缓存之 + // 还有Track未就绪,先缓存之 frame_unread.emplace_back(Frame::getCacheAbleFrame(frame)); return true; }); @@ -62,36 +66,37 @@ bool MediaSink::addTrack(const Track::Ptr &track_in) { } void MediaSink::resetTracks() { - _all_track_ready = false; + _audio_add = false; _have_video = false; - _track_map.clear(); - _track_ready_callback.clear(); + _all_track_ready = false; + _mute_audio_maker = nullptr; _ticker.resetTime(); - _max_track_size = 2; + _track_map.clear(); _frame_unread.clear(); + _track_ready_callback.clear(); } bool MediaSink::inputFrame(const Frame::Ptr &frame) { - auto it = _track_map.find(frame->getTrackType()); + auto it = _track_map.find(frame->getIndex()); if (it == _track_map.end()) { return false; } - //got frame + // got frame it->second.second = true; auto ret = it->second.first->inputFrame(frame); if (_mute_audio_maker && frame->getTrackType() == TrackVideo) { - //视频驱动产生静音音频 + // 视频驱动产生静音音频 _mute_audio_maker->inputFrame(frame); } checkTrackIfReady(); return ret; } -void MediaSink::checkTrackIfReady(){ +void MediaSink::checkTrackIfReady() { if (!_all_track_ready && !_track_ready_callback.empty()) { for (auto &pr : _track_map) { if (pr.second.second && pr.second.first->ready()) { - //Track由未就绪状态转换成就绪状态,我们就触发onTrackReady回调 + // Track由未就绪状态转换成就绪状态,我们就触发onTrackReady回调 auto it = _track_ready_callback.find(pr.first); if (it != _track_ready_callback.end()) { it->second(); @@ -101,28 +106,34 @@ void MediaSink::checkTrackIfReady(){ } } - if(!_all_track_ready){ + if (!_all_track_ready) { GET_CONFIG(uint32_t, kMaxWaitReadyMS, General::kWaitTrackReadyMS); - if(_ticker.elapsedTime() > kMaxWaitReadyMS){ - //如果超过规定时间,那么不再等待并忽略未准备好的Track + if (_ticker.elapsedTime() > kMaxWaitReadyMS) { + // 如果超过规定时间,那么不再等待并忽略未准备好的Track emitAllTrackReady(); return; } - if(!_track_ready_callback.empty()){ - //在超时时间内,如果存在未准备好的Track,那么继续等待 + if (!_track_ready_callback.empty()) { + // 在超时时间内,如果存在未准备好的Track,那么继续等待 return; } - if(_track_map.size() == _max_track_size){ - //如果已经添加了音视频Track,并且不存在未准备好的Track,那么说明所有Track都准备好了 + if (_only_audio && _audio_add) { + // 只开启音频 + emitAllTrackReady(); + return; + } + + if (_track_map.size() == _max_track_size) { + // 如果已经添加了音视频Track,并且不存在未准备好的Track,那么说明所有Track都准备好了 emitAllTrackReady(); return; } GET_CONFIG(uint32_t, kMaxAddTrackMS, General::kWaitAddTrackMS); - if(_track_map.size() == 1 && _ticker.elapsedTime() > kMaxAddTrackMS){ - //如果只有一个Track,那么在该Track添加后,我们最多还等待若干时间(可能后面还会添加Track) + if (_track_map.size() == 1 && _ticker.elapsedTime() > kMaxAddTrackMS) { + // 如果只有一个Track,那么在该Track添加后,我们最多还等待若干时间(可能后面还会添加Track) emitAllTrackReady(); return; } @@ -138,7 +149,7 @@ void MediaSink::setMaxTrackCount(size_t i) { WarnL << "All track is ready, set max track count ignored"; return; } - _max_track_size = MAX(MIN(i, 2), 1); + _max_track_size = MAX(i, 1); checkTrackIfReady(); } @@ -149,9 +160,9 @@ void MediaSink::emitAllTrackReady() { DebugL << "All track ready use " << _ticker.elapsedTime() << "ms"; if (!_track_ready_callback.empty()) { - //这是超时强制忽略未准备好的Track + // 这是超时强制忽略未准备好的Track _track_ready_callback.clear(); - //移除未准备好的Track + // 移除未准备好的Track for (auto it = _track_map.begin(); it != _track_map.end();) { if (!it->second.second || !it->second.first->ready()) { WarnL << "Track not ready for a long time, ignored: " << it->second.first->getCodecName(); @@ -163,25 +174,23 @@ void MediaSink::emitAllTrackReady() { } if (!_track_map.empty()) { - //最少有一个有效的Track + // 最少有一个有效的Track onAllTrackReady_l(); - //全部Track就绪,我们一次性把之前的帧输出 - for(auto &pr : _frame_unread){ + // 全部Track就绪,我们一次性把之前的帧输出 + for (auto &pr : _frame_unread) { if (_track_map.find(pr.first) == _track_map.end()) { - //该Track已经被移除 + // 该Track已经被移除 continue; } - pr.second.for_each([&](const Frame::Ptr &frame) { - MediaSink::inputFrame(frame); - }); + pr.second.for_each([&](const Frame::Ptr &frame) { MediaSink::inputFrame(frame); }); } _frame_unread.clear(); } } void MediaSink::onAllTrackReady_l() { - //是否添加静音音频 + // 是否添加静音音频 if (_add_mute_audio) { addMuteAudioTrack(); } @@ -190,10 +199,10 @@ void MediaSink::onAllTrackReady_l() { _have_video = (bool)getTrack(TrackVideo); } -vector MediaSink::getTracks(bool ready) const{ +vector MediaSink::getTracks(bool ready) const { vector ret; - for (auto &pr : _track_map){ - if(ready && !pr.second.first->ready()){ + for (auto &pr : _track_map) { + if (ready && !pr.second.first->ready()) { continue; } ret.emplace_back(pr.second.first); @@ -201,17 +210,6 @@ vector MediaSink::getTracks(bool ready) const{ return ret; } -class FrameFromStaticPtr : public FrameFromPtr { -public: - template - FrameFromStaticPtr(ARGS &&...args) : FrameFromPtr(std::forward(args)...) {}; - ~FrameFromStaticPtr() override = default; - - bool cacheAble() const override { - return true; - } -}; - static uint8_t s_mute_adts[] = {0xff, 0xf1, 0x6c, 0x40, 0x2d, 0x3f, 0xfc, 0x00, 0xe0, 0x34, 0x20, 0xad, 0xf2, 0x3f, 0xb5, 0xdd, 0x73, 0xac, 0xbd, 0xca, 0xd7, 0x7d, 0x4a, 0x13, 0x2d, 0x2e, 0xa2, 0x62, 0x02, 0x70, 0x3c, 0x1c, 0xc5, 0x63, 0x55, 0x69, 0x94, 0xb5, 0x8d, 0x70, 0xd7, 0x24, 0x6a, 0x9e, 0x2e, 0x86, 0x24, 0xea, @@ -237,18 +235,24 @@ static uint8_t s_mute_adts[] = {0xff, 0xf1, 0x6c, 0x40, 0x2d, 0x3f, 0xfc, 0x00, 0xc5, 0x97, 0x39, 0x6a, 0xb8, 0xa2, 0x55, 0xa8, 0xf8}; #define MUTE_ADTS_DATA s_mute_adts -#define MUTE_ADTS_DATA_LEN sizeof(s_mute_adts) #define MUTE_ADTS_DATA_MS 128 +static uint8_t ADTS_CONFIG[2] = { 0x15, 0x88 }; bool MuteAudioMaker::inputFrame(const Frame::Ptr &frame) { - if (frame->getTrackType() == TrackVideo) { - auto audio_idx = frame->dts() / MUTE_ADTS_DATA_MS; - if (_audio_idx != audio_idx) { - _audio_idx = audio_idx; - auto aacFrame = std::make_shared(CodecAAC, (char *) MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN, - _audio_idx * MUTE_ADTS_DATA_MS, 0, ADTS_HEADER_LEN); - return FrameDispatcher::inputFrame(aacFrame); - } + if (_track_index == -1) { + // 锁定track + _track_index = frame->getIndex(); + } + if (frame->getIndex() != _track_index) { + // 不是锁定的track + return false; + } + auto audio_idx = frame->dts() / MUTE_ADTS_DATA_MS; + if (_audio_idx != audio_idx) { + _audio_idx = audio_idx; + auto aacFrame = std::make_shared>(CodecAAC, (char *)MUTE_ADTS_DATA, sizeof(s_mute_adts), _audio_idx * MUTE_ADTS_DATA_MS, 0, 7); + aacFrame->setIndex(MUTE_AUDIO_INDEX); + return FrameDispatcher::inputFrame(aacFrame); } return false; } @@ -257,18 +261,18 @@ bool MediaSink::addMuteAudioTrack() { if (!_enable_audio) { return false; } - if (_track_map.find(TrackAudio) != _track_map.end()) { - return false; + for (auto &pr : _track_map) { + if (pr.second.first->getTrackType() == TrackAudio) { + return false; + } } - auto audio = std::make_shared(makeAacConfig(MUTE_ADTS_DATA, ADTS_HEADER_LEN)); - _track_map[audio->getTrackType()] = std::make_pair(audio, true); - audio->addDelegate([this](const Frame::Ptr &frame) { - return onTrackFrame(frame); - }); + auto audio = Factory::getTrackByCodecId(CodecAAC); + audio->setIndex(MUTE_AUDIO_INDEX); + audio->setExtraData(ADTS_CONFIG, 2); + _track_map[MUTE_AUDIO_INDEX] = std::make_pair(audio, true); + audio->addDelegate([this](const Frame::Ptr &frame) { return onTrackFrame(frame); }); _mute_audio_maker = std::make_shared(); - _mute_audio_maker->addDelegate([audio](const Frame::Ptr &frame) { - return audio->inputFrame(frame); - }); + _mute_audio_maker->addDelegate([audio](const Frame::Ptr &frame) { return audio->inputFrame(frame); }); onTrackReady(audio); TraceL << "Mute aac track added"; return true; @@ -280,14 +284,12 @@ bool MediaSink::isAllTrackReady() const { void MediaSink::enableAudio(bool flag) { _enable_audio = flag; - _max_track_size = flag ? 2 : 1; } -void MediaSink::setOnlyAudio(){ +void MediaSink::setOnlyAudio() { _only_audio = true; _enable_audio = true; _add_mute_audio = false; - _max_track_size = 1; } void MediaSink::enableMuteAudio(bool flag) { @@ -342,9 +344,7 @@ bool Demuxer::addTrack(const Track::Ptr &track) { } if (_sink->addTrack(track)) { - track->addDelegate([this](const Frame::Ptr &frame) { - return _sink->inputFrame(frame); - }); + track->addDelegate([this](const Frame::Ptr &frame) { return _sink->inputFrame(frame); }); return true; } return false; @@ -380,4 +380,4 @@ vector Demuxer::getTracks(bool ready) const { } return ret; } -}//namespace mediakit +} // namespace mediakit diff --git a/src/Common/MediaSink.h b/src/Common/MediaSink.h index ea207bae..683878e3 100644 --- a/src/Common/MediaSink.h +++ b/src/Common/MediaSink.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -21,7 +21,6 @@ namespace mediakit{ class TrackListener { public: - TrackListener() = default; virtual ~TrackListener() = default; /** @@ -45,9 +44,6 @@ public: class MediaSinkInterface : public FrameWriterInterface, public TrackListener { public: using Ptr = std::shared_ptr; - - MediaSinkInterface() = default; - ~MediaSinkInterface() override = default; }; /** @@ -56,11 +52,10 @@ public: class MuteAudioMaker : public FrameDispatcher { public: using Ptr = std::shared_ptr; - MuteAudioMaker() = default; - ~MuteAudioMaker() override = default; bool inputFrame(const Frame::Ptr &frame) override; private: + int _track_index = -1; uint64_t _audio_idx = 0; }; @@ -71,9 +66,6 @@ private: class MediaSink : public MediaSinkInterface, public TrackSource{ public: using Ptr = std::shared_ptr; - MediaSink() = default; - ~MediaSink() override = default; - /** * 输入frame * @param frame @@ -95,7 +87,7 @@ public: void addTrackCompleted() override; /** - * 设置最大track数,取值范围1~2;该方法与addTrackCompleted类型; + * 设置最大track数,取值范围>=1;该方法与addTrackCompleted类型; * 在设置单track时,可以加快媒体注册速度 */ void setMaxTrackCount(size_t i); @@ -112,7 +104,7 @@ public: std::vector getTracks(bool trackReady = true) const override; /** - * 返回是否所有track已经准备完成 + * 判断是否已经触发onAllTrackReady事件 */ bool isAllTrackReady() const; @@ -172,25 +164,25 @@ private: bool addMuteAudioTrack(); private: + bool _audio_add = false; + bool _have_video = false; bool _enable_audio = true; bool _only_audio = false; bool _add_mute_audio = true; bool _all_track_ready = false; - bool _have_video = false; size_t _max_track_size = 2; - std::unordered_map > _track_map; - std::unordered_map > _frame_unread; - std::unordered_map > _track_ready_callback; + toolkit::Ticker _ticker; MuteAudioMaker::Ptr _mute_audio_maker; + + std::unordered_map > _frame_unread; + std::unordered_map > _track_ready_callback; + std::unordered_map > _track_map; }; class MediaSinkDelegate : public MediaSink { public: - MediaSinkDelegate() = default; - ~MediaSinkDelegate() override = default; - /** * 设置track监听器 */ @@ -207,9 +199,6 @@ private: class Demuxer : protected TrackListener, public TrackSource { public: - Demuxer() = default; - ~Demuxer() override = default; - void setTrackListener(TrackListener *listener, bool wait_track_ready = false); std::vector getTracks(bool trackReady = true) const override; diff --git a/src/Common/MediaSource.cpp b/src/Common/MediaSource.cpp index 1977b616..184550e0 100644 --- a/src/Common/MediaSource.cpp +++ b/src/Common/MediaSource.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -60,6 +60,7 @@ ProtocolOption::ProtocolOption() { GET_CONFIG(bool, s_add_mute_audio, Protocol::kAddMuteAudio); GET_CONFIG(bool, s_auto_close, Protocol::kAutoClose); GET_CONFIG(uint32_t, s_continue_push_ms, Protocol::kContinuePushMS); + GET_CONFIG(uint32_t, s_paced_sender_ms, Protocol::kPacedSenderMS); GET_CONFIG(bool, s_enable_hls, Protocol::kEnableHls); GET_CONFIG(bool, s_enable_hls_fmp4, Protocol::kEnableHlsFmp4); @@ -86,6 +87,7 @@ ProtocolOption::ProtocolOption() { add_mute_audio = s_add_mute_audio; auto_close = s_auto_close; continue_push_ms = s_continue_push_ms; + paced_sender_ms = s_paced_sender_ms; enable_hls = s_enable_hls; enable_hls_fmp4 = s_enable_hls_fmp4; @@ -489,7 +491,19 @@ MediaSource::Ptr MediaSource::find(const string &vhost, const string &app, const if (src) { return src; } - return MediaSource::find(HLS_SCHEMA, vhost, app, stream_id, from_mp4); + src = MediaSource::find(TS_SCHEMA, vhost, app, stream_id, from_mp4); + if (src) { + return src; + } + src = MediaSource::find(FMP4_SCHEMA, vhost, app, stream_id, from_mp4); + if (src) { + return src; + } + src = MediaSource::find(HLS_SCHEMA, vhost, app, stream_id, from_mp4); + if (src) { + return src; + } + return MediaSource::find(HLS_FMP4_SCHEMA, vhost, app, stream_id, from_mp4); } void MediaSource::emitEvent(bool regist){ diff --git a/src/Common/MediaSource.h b/src/Common/MediaSource.h index 9721210a..4c6b33e9 100644 --- a/src/Common/MediaSource.h +++ b/src/Common/MediaSource.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -50,10 +50,8 @@ public: public: template NotImplemented(T && ...args) : std::runtime_error(std::forward(args)...) {} - ~NotImplemented() override = default; }; - MediaSourceEvent() = default; virtual ~MediaSourceEvent() = default; // 获取媒体源类型 @@ -161,6 +159,10 @@ public: //断连续推延时,单位毫秒,默认采用配置文件 uint32_t continue_push_ms; + // 平滑发送定时器间隔,单位毫秒,置0则关闭;开启后影响cpu性能同时增加内存 + // 该配置开启后可以解决一些流发送不平滑导致zlmediakit转发也不平滑的问题 + uint32_t paced_sender_ms; + //是否开启转换为hls(mpegts) bool enable_hls; //是否开启转换为hls(fmp4) @@ -200,6 +202,9 @@ public: // 支持通过on_publish返回值替换stream_id std::string stream_replace; + // 最大track数 + size_t max_track = 2; + template ProtocolOption(const MAP &allArgs) : ProtocolOption() { load(allArgs); @@ -213,6 +218,7 @@ public: GET_OPT_VALUE(add_mute_audio); GET_OPT_VALUE(auto_close); GET_OPT_VALUE(continue_push_ms); + GET_OPT_VALUE(paced_sender_ms); GET_OPT_VALUE(enable_hls); GET_OPT_VALUE(enable_hls_fmp4); @@ -234,6 +240,7 @@ public: GET_OPT_VALUE(hls_save_path); GET_OPT_VALUE(stream_replace); + GET_OPT_VALUE(max_track); } private: @@ -249,9 +256,6 @@ private: //该对象用于拦截感兴趣的MediaSourceEvent事件 class MediaSourceEventInterceptor : public MediaSourceEvent { public: - MediaSourceEventInterceptor() = default; - ~MediaSourceEventInterceptor() override = default; - void setDelegate(const std::weak_ptr &listener); std::shared_ptr getDelegate() const; @@ -284,7 +288,6 @@ private: */ class MediaInfo: public MediaTuple { public: - ~MediaInfo() = default; MediaInfo() = default; MediaInfo(const std::string &url) { parse(url); } void parse(const std::string &url); diff --git a/src/Common/MultiMediaSourceMuxer.cpp b/src/Common/MultiMediaSourceMuxer.cpp index fa86134b..b4753d51 100644 --- a/src/Common/MultiMediaSourceMuxer.cpp +++ b/src/Common/MultiMediaSourceMuxer.cpp @@ -1,9 +1,9 @@ /* -* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. +* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * -* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). +* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * -* Use of this source code is governed by MIT license that can be found in the +* Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -32,6 +32,87 @@ public: }; } // namespace +class FramePacedSender : public FrameWriterInterface, public std::enable_shared_from_this { +public: + using OnFrame = std::function; + // 最小缓存100ms数据 + static constexpr auto kMinCacheMS = 100; + + FramePacedSender(uint32_t paced_sender_ms, OnFrame cb) { + _paced_sender_ms = paced_sender_ms; + _cb = std::move(cb); + } + + void resetTimer(const EventPoller::Ptr &poller) { + std::weak_ptr weak_self = shared_from_this(); + _timer = std::make_shared(_paced_sender_ms / 1000.0f, [weak_self]() { + if (auto strong_self = weak_self.lock()) { + strong_self->onTick(); + return true; + } + return false; + }, poller); + } + + bool inputFrame(const Frame::Ptr &frame) override { + if (!_timer) { + setCurrentStamp(frame->dts()); + resetTimer(EventPoller::getCurrentPoller()); + } + + _cache.emplace_back(frame->dts() + _cache_ms, Frame::getCacheAbleFrame(frame)); + return true; + } + +private: + void onTick() { + auto dst = _cache.empty() ? 0 : _cache.back().first; + while (!_cache.empty()) { + auto &front = _cache.front(); + if (getCurrentStamp() < front.first) { + // 还没到消费时间 + break; + } + // 时间到了,该消费frame了 + _cb(front.second); + _cache.pop_front(); + } + + if (_cache.empty() && dst) { + // 消费太快,需要增加缓存大小 + setCurrentStamp(dst); + _cache_ms += kMinCacheMS; + } + + // 消费太慢,需要强制flush数据 + if (_cache.size() > 25 * 5) { + WarnL << "Flush frame paced sender cache: " << _cache.size(); + while (!_cache.empty()) { + auto &front = _cache.front(); + _cb(front.second); + _cache.pop_front(); + } + setCurrentStamp(dst); + } + } + + uint64_t getCurrentStamp() { return _ticker.elapsedTime() + _stamp_offset; } + + void setCurrentStamp(uint64_t stamp) { + _stamp_offset = stamp; + _ticker.resetTime(); + } + +private: + uint32_t _paced_sender_ms; + uint32_t _cache_ms = kMinCacheMS; + uint64_t _stamp_offset = 0; + OnFrame _cb; + Ticker _ticker; + Timer::Ptr _timer; + std::list> _cache; +}; + static std::shared_ptr makeRecorder(MediaSource &sender, const vector &tracks, Recorder::type type, const ProtocolOption &option){ auto recorder = Recorder::createRecorder(type, sender.getMediaTuple(), option); for (auto &track : tracks) { @@ -96,11 +177,8 @@ MultiMediaSourceMuxer::MultiMediaSourceMuxer(const MediaTuple& tuple, float dur_ _poller = EventPollerPool::Instance().getPoller(); _create_in_poller = _poller->isCurrentThread(); _option = option; - if (dur_sec > 0.01) { - // 点播 - _stamp[TrackVideo].setPlayBack(); - _stamp[TrackAudio].setPlayBack(); - } + _dur_sec = dur_sec; + setMaxTrackCount(option.max_track); if (option.enable_rtmp) { _rtmp = std::make_shared(_tuple, option, std::make_shared(dur_sec)); @@ -371,6 +449,9 @@ EventPoller::Ptr MultiMediaSourceMuxer::getOwnerPoller(MediaSource &sender) { if (ret != _poller) { WarnL << "OwnerPoller changed " << _poller->getThreadName() << " -> " << ret->getThreadName() << " : " << shortUrl(); _poller = ret; + if (_paced_sender) { + _paced_sender->resetTimer(_poller); + } } return ret; } catch (MediaSourceEvent::NotImplemented &) { @@ -384,6 +465,12 @@ std::shared_ptr MultiMediaSourceMuxer::getMuxer(MediaSour } bool MultiMediaSourceMuxer::onTrackReady(const Track::Ptr &track) { + auto &stamp = _stamps[track->getIndex()]; + if (_dur_sec > 0.01) { + // 点播 + stamp.setPlayBack(); + } + bool ret = false; if (_rtmp) { ret = _rtmp->addTrack(track) ? true : ret; @@ -411,6 +498,16 @@ bool MultiMediaSourceMuxer::onTrackReady(const Track::Ptr &track) { void MultiMediaSourceMuxer::onAllTrackReady() { CHECK(!_create_in_poller || getOwnerPoller(MediaSource::NullMediaSource())->isCurrentThread()); + + if (_option.paced_sender_ms) { + std::weak_ptr weak_self = shared_from_this(); + _paced_sender = std::make_shared(_option.paced_sender_ms, [weak_self](const Frame::Ptr &frame) { + if (auto strong_self = weak_self.lock()) { + strong_self->onTrackFrame_l(frame); + } + }); + } + setMediaListener(getDelegate()); if (_rtmp) { @@ -446,10 +543,14 @@ void MultiMediaSourceMuxer::onAllTrackReady() { createGopCacheIfNeed(); } #endif - auto tracks = getTracks(false); - if (tracks.size() >= 2) { - // 音频时间戳同步于视频,因为音频时间戳被修改后不影响播放 - _stamp[TrackAudio].syncTo(_stamp[TrackVideo]); + + Stamp *first = nullptr; + for (auto &pr : _stamps) { + if (!first) { + first = &pr.second; + } else { + pr.second.syncTo(*first); + } } InfoL << "stream: " << shortUrl() << " , codec info: " << getTrackInfoStr(this); } @@ -496,13 +597,15 @@ void MultiMediaSourceMuxer::resetTracks() { } } -bool MultiMediaSourceMuxer::onTrackFrame(const Frame::Ptr &frame_in) { - auto frame = frame_in; +bool MultiMediaSourceMuxer::onTrackFrame(const Frame::Ptr &frame) { if (_option.modify_stamp != ProtocolOption::kModifyStampOff) { // 时间戳不采用原始的绝对时间戳 - frame = std::make_shared(frame, _stamp[frame->getTrackType()], _option.modify_stamp); + const_cast(frame) = std::make_shared(frame, _stamps[frame->getIndex()], _option.modify_stamp); } + return _paced_sender ? _paced_sender->inputFrame(frame) : onTrackFrame_l(frame); +} +bool MultiMediaSourceMuxer::onTrackFrame_l(const Frame::Ptr &frame) { bool ret = false; if (_rtmp) { ret = _rtmp->inputFrame(frame) ? true : ret; @@ -530,7 +633,7 @@ bool MultiMediaSourceMuxer::onTrackFrame(const Frame::Ptr &frame_in) { } if (_ring) { // 此场景由于直接转发,可能存在切换线程引起的数据被缓存在管道,所以需要CacheAbleFrame - frame = Frame::getCacheAbleFrame(frame); + const_cast(frame) = Frame::getCacheAbleFrame(frame); if (frame->getTrackType() == TrackVideo) { // 视频时,遇到第一帧配置帧或关键帧则标记为gop开始处 auto video_key_pos = frame->keyFrame() || frame->configFrame(); diff --git a/src/Common/MultiMediaSourceMuxer.h b/src/Common/MultiMediaSourceMuxer.h index c35ef5e9..d51dcea6 100644 --- a/src/Common/MultiMediaSourceMuxer.h +++ b/src/Common/MultiMediaSourceMuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -32,13 +32,11 @@ public: class Listener { public: - Listener() = default; virtual ~Listener() = default; virtual void onAllTrackReady() = 0; }; MultiMediaSourceMuxer(const MediaTuple& tuple, float dur_sec = 0.0,const ProtocolOption &option = ProtocolOption()); - ~MultiMediaSourceMuxer() override = default; /** * 设置事件监听器 @@ -160,6 +158,7 @@ protected: * @param frame */ bool onTrackFrame(const Frame::Ptr &frame) override; + bool onTrackFrame_l(const Frame::Ptr &frame); private: void createGopCacheIfNeed(); @@ -168,10 +167,12 @@ private: bool _is_enable = false; bool _create_in_poller = false; bool _video_key_pos = false; + float _dur_sec; + std::shared_ptr _paced_sender; MediaTuple _tuple; ProtocolOption _option; toolkit::Ticker _last_check; - Stamp _stamp[2]; + std::unordered_map _stamps; std::weak_ptr _track_listener; std::unordered_multimap _rtp_sender; FMP4MediaSourceMuxer::Ptr _fmp4; diff --git a/src/Common/PacketCache.h b/src/Common/PacketCache.h index fd9032a1..5e930a5f 100644 --- a/src/Common/PacketCache.h +++ b/src/Common/PacketCache.h @@ -1,9 +1,9 @@ /* -* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. +* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * -* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). +* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * -* Use of this source code is governed by MIT license that can be found in the +* Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -18,9 +18,6 @@ namespace mediakit { /// 缓存刷新策略类 class FlushPolicy { public: - FlushPolicy() = default; - ~FlushPolicy() = default; - bool isFlushAble(bool is_video, bool is_key, uint64_t new_stamp, size_t cache_size); private: @@ -79,13 +76,8 @@ private: // 但是却对性能提升很大,这样做还是比较划算的 GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); - GET_CONFIG(int, rtspLowLatency, Rtsp::kLowLatency); - if (std::is_same::value && rtspLowLatency) { - return true; - } - - return std::is_same::value ? false : (mergeWriteMS <= 0); + return std::is_same::value ? rtspLowLatency : (mergeWriteMS <= 0); } private: diff --git a/src/Common/Parser.cpp b/src/Common/Parser.cpp index 15636c33..ab41c53e 100644 --- a/src/Common/Parser.cpp +++ b/src/Common/Parser.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -293,7 +293,6 @@ void RtspUrl::setup(bool is_ssl, const string &url, const string &user, const st uint16_t port = is_ssl ? 322 : 554; splitUrl(ip, ip, port); - _url = std::move(url); _user = strCoding::UrlDecode(std::move(user)); _passwd = strCoding::UrlDecode(std::move(passwd)); diff --git a/src/Common/Parser.h b/src/Common/Parser.h index a2165ce1..624e5f27 100644 --- a/src/Common/Parser.h +++ b/src/Common/Parser.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -31,8 +31,6 @@ struct StrCaseCompare { class StrCaseMap : public std::multimap { public: using Super = multimap; - StrCaseMap() = default; - ~StrCaseMap() = default; std::string &operator[](const std::string &k) { auto it = find(k); @@ -60,9 +58,6 @@ public: // rtsp/http/sip解析类 class Parser { public: - Parser() = default; - ~Parser() = default; - // 解析http/rtsp/sip请求,需要确保buf以\0结尾 void parse(const char *buf, size_t size); @@ -132,8 +127,6 @@ public: std::string _host; public: - RtspUrl() = default; - ~RtspUrl() = default; void parse(const std::string &url); private: diff --git a/src/Common/Stamp.cpp b/src/Common/Stamp.cpp index 47d344a7..892d2565 100644 --- a/src/Common/Stamp.cpp +++ b/src/Common/Stamp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Common/Stamp.h b/src/Common/Stamp.h index 243c250c..0b525748 100644 --- a/src/Common/Stamp.h +++ b/src/Common/Stamp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -17,10 +17,10 @@ namespace mediakit { -class DeltaStamp{ +class DeltaStamp { public: DeltaStamp(); - ~DeltaStamp() = default; + virtual ~DeltaStamp() = default; /** * 计算时间戳增量 @@ -48,9 +48,6 @@ protected: //计算相对时间戳或者产生平滑时间戳 class Stamp : public DeltaStamp{ public: - Stamp() = default; - ~Stamp() = default; - /** * 求取相对时间戳,同时实现了音视频同步、限制dts回退等功能 * @param dts 输入dts,如果为0则根据系统时间戳生成 @@ -116,8 +113,6 @@ private: //pts排序后就是dts class DtsGenerator{ public: - DtsGenerator() = default; - ~DtsGenerator() = default; bool getDts(uint64_t pts, uint64_t &dts); private: @@ -136,9 +131,6 @@ private: class NtpStamp { public: - NtpStamp() = default; - ~NtpStamp() = default; - void setNtpStamp(uint32_t rtp_stamp, uint64_t ntp_stamp_ms); uint64_t getNtpStamp(uint32_t rtp_stamp, uint32_t sample_rate); diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 1009f1e6..82b3feca 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -101,6 +101,7 @@ const string kEnableAudio = PROTOCOL_FIELD "enable_audio"; const string kAddMuteAudio = PROTOCOL_FIELD "add_mute_audio"; const string kAutoClose = PROTOCOL_FIELD "auto_close"; const string kContinuePushMS = PROTOCOL_FIELD "continue_push_ms"; +const string kPacedSenderMS = PROTOCOL_FIELD "paced_sender_ms"; const string kEnableHls = PROTOCOL_FIELD "enable_hls"; const string kEnableHlsFmp4 = PROTOCOL_FIELD "enable_hls_fmp4"; @@ -127,6 +128,7 @@ static onceToken token([]() { mINI::Instance()[kEnableAudio] = 1; mINI::Instance()[kAddMuteAudio] = 1; mINI::Instance()[kContinuePushMS] = 15000; + mINI::Instance()[kPacedSenderMS] = 0; mINI::Instance()[kAutoClose] = 0; mINI::Instance()[kEnableHls] = 1; @@ -233,10 +235,14 @@ namespace Rtmp { #define RTMP_FIELD "rtmp." const string kHandshakeSecond = RTMP_FIELD "handshakeSecond"; const string kKeepAliveSecond = RTMP_FIELD "keepAliveSecond"; +const string kDirectProxy = RTMP_FIELD "directProxy"; +const string kEnhanced = RTMP_FIELD "enhanced"; static onceToken token([]() { mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15; + mINI::Instance()[kDirectProxy] = 1; + mINI::Instance()[kEnhanced] = 1; }); } // namespace Rtmp @@ -305,6 +311,7 @@ const string kSegmentRetain = HLS_FIELD "segRetain"; const string kFileBufSize = HLS_FIELD "fileBufSize"; const string kBroadcastRecordTs = HLS_FIELD "broadcastRecordTs"; const string kDeleteDelaySec = HLS_FIELD "deleteDelaySec"; +const string kFastRegister = HLS_FIELD "fastRegister"; static onceToken token([]() { mINI::Instance()[kSegmentDuration] = 2; @@ -314,6 +321,7 @@ static onceToken token([]() { mINI::Instance()[kFileBufSize] = 64 * 1024; mINI::Instance()[kBroadcastRecordTs] = false; mINI::Instance()[kDeleteDelaySec] = 10; + mINI::Instance()[kFastRegister] = false; }); } // namespace Hls diff --git a/src/Common/config.h b/src/Common/config.h index dcbc5514..7f9073d9 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -196,6 +196,9 @@ extern const std::string kAddMuteAudio; extern const std::string kAutoClose; //断连续推延时,单位毫秒,默认采用配置文件 extern const std::string kContinuePushMS; +// 平滑发送定时器间隔,单位毫秒,置0则关闭;开启后影响cpu性能同时增加内存 +// 该配置开启后可以解决一些流发送不平滑导致zlmediakit转发也不平滑的问题 +extern const std::string kPacedSenderMS; //是否开启转换为hls(mpegts) extern const std::string kEnableHls; @@ -294,6 +297,10 @@ namespace Rtmp { extern const std::string kHandshakeSecond; // 维持链接超时时间,默认15秒 extern const std::string kKeepAliveSecond; +// 是否直接代理 +extern const std::string kDirectProxy; +// h265-rtmp是否采用增强型(或者国内扩展) +extern const std::string kEnhanced; } // namespace Rtmp ////////////RTP配置/////////// @@ -350,6 +357,8 @@ extern const std::string kFileBufSize; extern const std::string kBroadcastRecordTs; // hls直播文件删除延时,单位秒 extern const std::string kDeleteDelaySec; +// 如果设置为1,则第一个切片长度强制设置为1个GOP +extern const std::string kFastRegister; } // namespace Hls ////////////Rtp代理相关配置/////////// diff --git a/src/Common/macros.cpp b/src/Common/macros.cpp index 378c6ba1..3cb95c7b 100644 --- a/src/Common/macros.cpp +++ b/src/Common/macros.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -33,9 +33,13 @@ void Assert_Throw(int failed, const char *exp, const char *func, const char *fil namespace mediakit { -//请遵循MIT协议,勿修改服务器声明 +/** + * 本项目采用类MIT协议,用户在履行MIT协议义务的同时,应当同时遵循保留ZLMediaKit软件版权信息的义务。 + * 用户不得去除ZLMediaKit提供的各种服务中包括但不限于 "title"、"Server"、"User-Agent" 等字段中 "ZLMediaKit" 的信息。 + * 否则本项目主要权利人(项目发起人、主要作者)保留声索起诉的权利。 + */ #if !defined(ENABLE_VERSION) -const char kServerName[] = "ZLMediaKit-7.0(build in " __DATE__ " " __TIME__ ")"; +const char kServerName[] = "ZLMediaKit-8.0(build in " __DATE__ " " __TIME__ ")"; #else const char kServerName[] = "ZLMediaKit(git hash:" COMMIT_HASH "/" COMMIT_TIME ",branch:" BRANCH_NAME ",build time:" BUILD_TIME ")"; #endif diff --git a/src/Common/macros.h b/src/Common/macros.h index 8c86fc10..796bd326 100644 --- a/src/Common/macros.h +++ b/src/Common/macros.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -51,16 +51,14 @@ } #endif // CLEAR_ARR -#define VHOST_KEY "vhost" -#define HTTP_SCHEMA "http" #define RTSP_SCHEMA "rtsp" -#define RTC_SCHEMA "rtc" #define RTMP_SCHEMA "rtmp" -#define HLS_SCHEMA "hls" #define TS_SCHEMA "ts" #define FMP4_SCHEMA "fmp4" +#define HLS_SCHEMA "hls" #define HLS_FMP4_SCHEMA "hls.fmp4" -#define SRT_SCHEMA "srt" + +#define VHOST_KEY "vhost" #define DEFAULT_VHOST "__defaultVhost__" #ifdef __cplusplus @@ -77,7 +75,6 @@ class AssertFailedException : public std::runtime_error { public: template AssertFailedException(T && ...args) : std::runtime_error(std::forward(args)...) {} - ~AssertFailedException() override = default; }; extern const char kServerName[]; diff --git a/src/Common/strCoding.cpp b/src/Common/strCoding.cpp index 4f6c4e53..2189416b 100644 --- a/src/Common/strCoding.cpp +++ b/src/Common/strCoding.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Common/strCoding.h b/src/Common/strCoding.h index 00177f74..4ddf8382 100644 --- a/src/Common/strCoding.h +++ b/src/Common/strCoding.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Extension/AAC.h b/src/Extension/AAC.h deleted file mode 100644 index 32cf934b..00000000 --- a/src/Extension/AAC.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef ZLMEDIAKIT_AAC_H -#define ZLMEDIAKIT_AAC_H - -#include "Frame.h" -#include "Track.h" -#define ADTS_HEADER_LEN 7 - -namespace mediakit{ - -std::string makeAacConfig(const uint8_t *hex, size_t length); -int getAacFrameLength(const uint8_t *hex, size_t length); -int dumpAacConfig(const std::string &config, size_t length, uint8_t *out, size_t out_size); -bool parseAacConfig(const std::string &config, int &samplerate, int &channels); - -/** - * aac音频通道 - */ -class AACTrack : public AudioTrack{ -public: - using Ptr = std::shared_ptr; - - /** - * 延后获取adts头信息 - * 在随后的inputFrame中获取adts头信息 - */ - AACTrack() = default; - - /** - * 构造aac类型的媒体 - * @param aac_cfg aac配置信息 - */ - AACTrack(const std::string &aac_cfg); - - /** - * 获取aac 配置信息 - */ - const std::string &getConfig() const; - - bool ready() override; - CodecId getCodecId() const override; - int getAudioChannel() const override; - int getAudioSampleRate() const override; - int getAudioSampleBit() const override; - bool inputFrame(const Frame::Ptr &frame) override; - bool update() override; - -private: - void onReady(); - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; - bool inputFrame_l(const Frame::Ptr &frame); - -private: - std::string _cfg; - int _channel = 0; - int _sampleRate = 0; - int _sampleBit = 16; -}; - -}//namespace mediakit -#endif //ZLMEDIAKIT_AAC_H \ No newline at end of file diff --git a/src/Extension/AACRtmp.cpp b/src/Extension/AACRtmp.cpp deleted file mode 100644 index f1fdbab9..00000000 --- a/src/Extension/AACRtmp.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#include "AACRtmp.h" -#include "Rtmp/Rtmp.h" - -using namespace std; -using namespace toolkit; - -namespace mediakit { - -static string getConfig(const RtmpPacket &thiz) { - string ret; - if ((RtmpAudioCodec)thiz.getRtmpCodecId() != RtmpAudioCodec::aac) { - return ret; - } - if (thiz.buffer.size() < 4) { - WarnL << "get aac config failed, rtmp packet is: " << hexdump(thiz.data(), thiz.size()); - return ret; - } - ret = thiz.buffer.substr(2); - return ret; -} - -void AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { - if (pkt->isConfigFrame()) { - _aac_cfg = getConfig(*pkt); - if (!_aac_cfg.empty()) { - onGetAAC(nullptr, 0, 0); - } - return; - } - - if (!_aac_cfg.empty()) { - onGetAAC(pkt->buffer.data() + 2, pkt->buffer.size() - 2, pkt->time_stamp); - } -} - -void AACRtmpDecoder::onGetAAC(const char* data, size_t len, uint32_t stamp) { - auto frame = FrameImp::create(); - frame->_codec_id = CodecAAC; - - //生成adts头 - char adts_header[32] = {0}; - auto size = dumpAacConfig(_aac_cfg, len, (uint8_t *) adts_header, sizeof(adts_header)); - if (size > 0) { - frame->_buffer.assign(adts_header, size); - frame->_prefix_size = size; - } else { - frame->_buffer.clear(); - frame->_prefix_size = 0; - } - - if(len > 0){ - //追加负载数据 - frame->_buffer.append(data, len); - frame->_dts = stamp; - } - - if(size > 0 || len > 0){ - //有adts头或者实际aac负载 - RtmpCodec::inputFrame(frame); - } -} - -///////////////////////////////////////////////////////////////////////////////////// - -AACRtmpEncoder::AACRtmpEncoder(const Track::Ptr &track) { - _track = dynamic_pointer_cast(track); -} - -void AACRtmpEncoder::makeConfigPacket() { - if (_track && _track->ready()) { - //从track中和获取aac配置信息 - _aac_cfg = _track->getConfig(); - } - - if (!_aac_cfg.empty()) { - makeAudioConfigPkt(); - } -} - -bool AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) { - if (_aac_cfg.empty()) { - if (frame->prefixSize()) { - // 包含adts头,从adts头获取aac配置信息 - _aac_cfg = makeAacConfig((uint8_t *)(frame->data()), frame->prefixSize()); - } - makeConfigPacket(); - } - - if (_aac_cfg.empty()) { - return false; - } - - auto pkt = RtmpPacket::create(); - // header - pkt->buffer.push_back(_audio_flv_flags); - pkt->buffer.push_back((uint8_t)RtmpAACPacketType::aac_raw); - // aac data - pkt->buffer.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); - pkt->body_size = pkt->buffer.size(); - pkt->chunk_id = CHUNK_AUDIO; - pkt->stream_index = STREAM_MEDIA; - pkt->time_stamp = frame->dts(); - pkt->type_id = MSG_AUDIO; - RtmpCodec::inputRtmp(pkt); - return true; -} - -void AACRtmpEncoder::makeAudioConfigPkt() { - _audio_flv_flags = getAudioRtmpFlags(std::make_shared(_aac_cfg)); - auto pkt = RtmpPacket::create(); - // header - pkt->buffer.push_back(_audio_flv_flags); - pkt->buffer.push_back((uint8_t)RtmpAACPacketType::aac_config_header); - // aac config - pkt->buffer.append(_aac_cfg); - pkt->body_size = pkt->buffer.size(); - pkt->chunk_id = CHUNK_AUDIO; - pkt->stream_index = STREAM_MEDIA; - pkt->time_stamp = 0; - pkt->type_id = MSG_AUDIO; - RtmpCodec::inputRtmp(pkt); -} - -}//namespace mediakit \ No newline at end of file diff --git a/src/Extension/AACRtp.h b/src/Extension/AACRtp.h deleted file mode 100644 index fd9de2a9..00000000 --- a/src/Extension/AACRtp.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef ZLMEDIAKIT_AACRTPCODEC_H -#define ZLMEDIAKIT_AACRTPCODEC_H - -#include "Rtsp/RtpCodec.h" -#include "Extension/AAC.h" -namespace mediakit{ -/** - * aac rtp转adts类 - */ -class AACRtpDecoder : public RtpCodec { -public: - using Ptr = std::shared_ptr; - - AACRtpDecoder(const Track::Ptr &track); - ~AACRtpDecoder() {} - - /** - * 输入rtp并解码 - * @param rtp rtp数据包 - * @param key_pos 此参数内部强制转换为false,请忽略之 - */ - bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override; - - CodecId getCodecId() const override { - return CodecAAC; - } - -protected: - AACRtpDecoder(); - -private: - void obtainFrame(); - void flushData(); - -private: - uint64_t _last_dts = 0; - std::string _aac_cfg; - FrameImp::Ptr _frame; -}; - - -/** - * aac adts转rtp类 - */ -class AACRtpEncoder : public AACRtpDecoder , public RtpInfo { -public: - using Ptr = std::shared_ptr; - - /** - * @param ui32Ssrc ssrc - * @param ui32MtuSize mtu 大小 - * @param ui32SampleRate 采样率 - * @param ui8PayloadType pt类型 - * @param ui8Interleaved rtsp interleaved 值 - */ - AACRtpEncoder(uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PayloadType = 97, - uint8_t ui8Interleaved = TrackAudio * 2); - ~AACRtpEncoder() {} - - /** - * 输入aac 数据,必须带dats头 - * @param frame 带dats头的aac数据 - */ - bool inputFrame(const Frame::Ptr &frame) override; - -private: - void makeAACRtp(const void *data, size_t len, bool mark, uint64_t stamp); - -private: - unsigned char _section_buf[1600]; -}; - -}//namespace mediakit - -#endif //ZLMEDIAKIT_AACRTPCODEC_H diff --git a/src/Extension/CommonRtmp.cpp b/src/Extension/CommonRtmp.cpp index 671e21a1..46aebf40 100644 --- a/src/Extension/CommonRtmp.cpp +++ b/src/Extension/CommonRtmp.cpp @@ -1,55 +1,35 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "CommonRtmp.h" -namespace mediakit{ - -CommonRtmpDecoder::CommonRtmpDecoder(CodecId codec) { - _codec = codec; - obtainFrame(); -} - -CodecId CommonRtmpDecoder::getCodecId() const { - return _codec; -} - -void CommonRtmpDecoder::obtainFrame() { - _frame = FrameImp::create(); - _frame->_codec_id = _codec; -} +namespace mediakit { void CommonRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &rtmp) { - //拷贝负载 - _frame->_buffer.assign(rtmp->buffer.data() + 1, rtmp->buffer.size() - 1); - _frame->_dts = rtmp->time_stamp; - //写入环形缓存 - RtmpCodec::inputFrame(_frame); - //创建下一帧 - obtainFrame(); + auto frame = FrameImp::create(); + frame->_codec_id = getTrack()->getCodecId(); + frame->_buffer.assign(rtmp->buffer.data() + 1, rtmp->buffer.size() - 1); + frame->_dts = rtmp->time_stamp; + RtmpCodec::inputFrame(frame); } ///////////////////////////////////////////////////////////////////////////////////// -CommonRtmpEncoder::CommonRtmpEncoder(const Track::Ptr &track) : CommonRtmpDecoder(track->getCodecId()) { - _audio_flv_flags = getAudioRtmpFlags(track); -} - bool CommonRtmpEncoder::inputFrame(const Frame::Ptr &frame) { if (!_audio_flv_flags) { - return false; + _audio_flv_flags = getAudioRtmpFlags(getTrack()); } auto rtmp = RtmpPacket::create(); - //header + // header rtmp->buffer.push_back(_audio_flv_flags); - //data + // data rtmp->buffer.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); rtmp->body_size = rtmp->buffer.size(); rtmp->chunk_id = CHUNK_AUDIO; diff --git a/src/Extension/CommonRtmp.h b/src/Extension/CommonRtmp.h index 8c28238a..636e9fb8 100644 --- a/src/Extension/CommonRtmp.h +++ b/src/Extension/CommonRtmp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -23,42 +23,26 @@ class CommonRtmpDecoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - ~CommonRtmpDecoder() override {} - /** * 构造函数 - * @param codec 编码id */ - CommonRtmpDecoder(CodecId codec); - - /** - * 返回编码类型ID - */ - CodecId getCodecId() const override; + CommonRtmpDecoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入Rtmp并解码 * @param rtmp Rtmp数据包 */ void inputRtmp(const RtmpPacket::Ptr &rtmp) override; - -private: - void obtainFrame(); - -private: - CodecId _codec; - FrameImp::Ptr _frame; }; /** * 通用 rtmp编码类 */ -class CommonRtmpEncoder : public CommonRtmpDecoder { +class CommonRtmpEncoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - CommonRtmpEncoder(const Track::Ptr &track); - ~CommonRtmpEncoder() override{} + CommonRtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入帧数据 @@ -66,7 +50,7 @@ public: bool inputFrame(const Frame::Ptr &frame) override; private: - uint8_t _audio_flv_flags = 0; + uint8_t _audio_flv_flags { 0 }; }; }//namespace mediakit diff --git a/src/Extension/CommonRtp.cpp b/src/Extension/CommonRtp.cpp index 68767a6f..cf395ef4 100644 --- a/src/Extension/CommonRtp.cpp +++ b/src/Extension/CommonRtp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -18,10 +18,6 @@ CommonRtpDecoder::CommonRtpDecoder(CodecId codec, size_t max_frame_size ){ obtainFrame(); } -CodecId CommonRtpDecoder::getCodecId() const { - return _codec; -} - void CommonRtpDecoder::obtainFrame() { _frame = FrameImp::create(); _frame->_codec_id = _codec; @@ -66,17 +62,12 @@ bool CommonRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool){ //////////////////////////////////////////////////////////////// -CommonRtpEncoder::CommonRtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, - uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved) - : CommonRtpDecoder(codec), RtpInfo(ssrc, mtu_size, sample_rate, payload_type, interleaved) { -} - bool CommonRtpEncoder::inputFrame(const Frame::Ptr &frame){ auto stamp = frame->pts(); auto ptr = frame->data() + frame->prefixSize(); auto len = frame->size() - frame->prefixSize(); auto remain_size = len; - auto max_size = getMaxSize(); + auto max_size = getRtpInfo().getMaxSize(); bool is_key = frame->keyFrame(); bool mark = false; while (remain_size > 0) { @@ -87,7 +78,7 @@ bool CommonRtpEncoder::inputFrame(const Frame::Ptr &frame){ rtp_size = remain_size; mark = true; } - RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, rtp_size, mark, stamp), is_key); + RtpCodec::inputRtp(getRtpInfo().makeRtp(frame->getTrackType(), ptr, rtp_size, mark, stamp), is_key); ptr += rtp_size; remain_size -= rtp_size; is_key = false; diff --git a/src/Extension/CommonRtp.h b/src/Extension/CommonRtp.h index 6553207e..96cb5457 100644 --- a/src/Extension/CommonRtp.h +++ b/src/Extension/CommonRtp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -23,8 +23,6 @@ class CommonRtpDecoder : public RtpCodec { public: using Ptr = std::shared_ptr ; - ~CommonRtpDecoder() override {} - /** * 构造函数 * @param codec 编码id @@ -32,11 +30,6 @@ public: */ CommonRtpDecoder(CodecId codec, size_t max_frame_size = 2 * 1024); - /** - * 返回编码类型ID - */ - CodecId getCodecId() const override; - /** * 输入rtp并解码 * @param rtp rtp数据包 @@ -59,23 +52,10 @@ private: /** * 通用 rtp编码类 */ -class CommonRtpEncoder : public CommonRtpDecoder, public RtpInfo { +class CommonRtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr ; - ~CommonRtpEncoder() override {} - - /** - * 构造函数 - * @param codec 编码类型 - * @param ssrc ssrc - * @param mtu_size mtu 大小 - * @param sample_rate 采样率 - * @param payload_type pt类型 - * @param interleaved rtsp interleaved 值 - */ - CommonRtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved); - /** * 输入帧数据并编码成rtp */ diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index 63a2bbd5..f69eead7 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -1,188 +1,86 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "Factory.h" #include "Rtmp/Rtmp.h" -#include "H264Rtmp.h" -#include "H265Rtmp.h" -#include "AACRtmp.h" -#include "CommonRtmp.h" -#include "H264Rtp.h" -#include "JPEGRtp.h" -#include "AACRtp.h" -#include "H265Rtp.h" -#include "CommonRtp.h" -#include "G711Rtp.h" -#include "Opus.h" -#include "G711.h" -#include "L16.h" -#include "JPEG.h" -#include "Util/base64.h" -#include "Common/Parser.h" #include "Common/config.h" using namespace std; +using namespace toolkit; -namespace mediakit{ +namespace mediakit { + +static std::unordered_map s_plugins; + +extern CodecPlugin h264_plugin; +extern CodecPlugin h265_plugin; +extern CodecPlugin jpeg_plugin; +extern CodecPlugin aac_plugin; +extern CodecPlugin opus_plugin; +extern CodecPlugin g711a_plugin; +extern CodecPlugin g711u_plugin; +extern CodecPlugin l16_plugin; + +REGISTER_CODEC(h264_plugin); +REGISTER_CODEC(h265_plugin); +REGISTER_CODEC(jpeg_plugin); +REGISTER_CODEC(aac_plugin); +REGISTER_CODEC(opus_plugin); +REGISTER_CODEC(g711a_plugin) +REGISTER_CODEC(g711u_plugin); +REGISTER_CODEC(l16_plugin); + +void Factory::registerPlugin(const CodecPlugin &plugin) { + InfoL << "Load codec: " << getCodecName(plugin.getCodec()); + s_plugins[(int)(plugin.getCodec())] = &plugin; +} Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) { auto codec = getCodecId(track->_codec); if (codec == CodecInvalid) { - //根据传统的payload type 获取编码类型以及采样率等信息 + // 根据传统的payload type 获取编码类型以及采样率等信息 codec = RtpPayload::getCodecId(track->_pt); } - switch (codec) { - case CodecG711A: - case CodecG711U: return std::make_shared(codec, track->_samplerate, track->_channel, 16); - case CodecL16: return std::make_shared(track->_samplerate, track->_channel); - case CodecOpus : return std::make_shared(); - - case CodecAAC : { - string aac_cfg_str = findSubString(track->_fmtp.data(), "config=", ";"); - if (aac_cfg_str.empty()) { - aac_cfg_str = findSubString(track->_fmtp.data(), "config=", nullptr); - } - if (aac_cfg_str.empty()) { - //如果sdp中获取不到aac config信息,那么在rtp也无法获取,那么忽略该Track - return nullptr; - } - string aac_cfg; - for (size_t i = 0; i < aac_cfg_str.size() / 2; ++i) { - unsigned int cfg; - sscanf(aac_cfg_str.substr(i * 2, 2).data(), "%02X", &cfg); - cfg &= 0x00FF; - aac_cfg.push_back((char) cfg); - } - return std::make_shared(aac_cfg); - } - - case CodecH264 : { - //a=fmtp:96 packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9oBQBboQAAAAwBAAAAPI8YMqA==,aM48gA== - auto map = Parser::parseArgs(track->_fmtp, ";", "="); - auto sps_pps = map["sprop-parameter-sets"]; - string base64_SPS = findSubString(sps_pps.data(), NULL, ","); - string base64_PPS = findSubString(sps_pps.data(), ",", NULL); - auto sps = decodeBase64(base64_SPS); - auto pps = decodeBase64(base64_PPS); - if (sps.empty() || pps.empty()) { - //如果sdp里面没有sps/pps,那么可能在后续的rtp里面恢复出sps/pps - return std::make_shared(); - } - return std::make_shared(sps, pps, 0, 0); - } - - case CodecH265: { - //a=fmtp:96 sprop-sps=QgEBAWAAAAMAsAAAAwAAAwBdoAKAgC0WNrkky/AIAAADAAgAAAMBlQg=; sprop-pps=RAHA8vA8kAA= - auto map = Parser::parseArgs(track->_fmtp, ";", "="); - auto vps = decodeBase64(map["sprop-vps"]); - auto sps = decodeBase64(map["sprop-sps"]); - auto pps = decodeBase64(map["sprop-pps"]); - if (sps.empty() || pps.empty()) { - //如果sdp里面没有sps/pps,那么可能在后续的rtp里面恢复出sps/pps - return std::make_shared(); - } - return std::make_shared(vps, sps, pps, 0, 0, 0); - } - - case CodecJPEG : { - return std::make_shared(); - } - - default: { - //其他codec不支持 - WarnL << "暂不支持该rtsp编码类型:" << track->getName(); - return nullptr; - } + auto it = s_plugins.find(codec); + if (it == s_plugins.end()) { + WarnL << "Unsupported codec: " << track->getName(); + return nullptr; } + return it->second->getTrackBySdp(track); } -Track::Ptr Factory::getTrackByAbstractTrack(const Track::Ptr& track) { +Track::Ptr Factory::getTrackByAbstractTrack(const Track::Ptr &track) { auto codec = track->getCodecId(); - switch (codec) { - case CodecG711A: - case CodecG711U: { - auto audio_track = dynamic_pointer_cast(track); - return std::make_shared(codec, audio_track->getAudioSampleRate(), audio_track->getAudioChannel(), 16); - } - case CodecL16: { - auto audio_track = dynamic_pointer_cast(track); - return std::make_shared(audio_track->getAudioSampleRate(), audio_track->getAudioChannel()); - } - case CodecAAC: return std::make_shared(); - case CodecOpus: return std::make_shared(); - case CodecH265: return std::make_shared(); - case CodecH264: return std::make_shared(); - case CodecJPEG: return std::make_shared(); - - default: { - //其他codec不支持 - WarnL << "暂不支持该该编码类型创建Track:" << track->getCodecName(); - return nullptr; - } + if (track->getTrackType() == TrackVideo) { + return getTrackByCodecId(codec); } + auto audio_track = dynamic_pointer_cast(track); + return getTrackByCodecId(codec, audio_track->getAudioSampleRate(), audio_track->getAudioChannel(), audio_track->getAudioSampleBit()); } -RtpCodec::Ptr Factory::getRtpEncoderByCodecId(CodecId codec_id, uint32_t sample_rate, uint8_t pt, uint32_t ssrc) { - GET_CONFIG(uint32_t, audio_mtu, Rtp::kAudioMtuSize); - GET_CONFIG(uint32_t, video_mtu, Rtp::kVideoMtuSize); - auto type = getTrackType(codec_id); - auto mtu = type == TrackVideo ? video_mtu : audio_mtu; - auto interleaved = type * 2; - switch (codec_id) { - case CodecH264: return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); - case CodecH265: return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); - case CodecAAC: return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); - case CodecL16: - case CodecOpus: return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved); - case CodecG711A: - case CodecG711U: { - if (pt == Rtsp::PT_PCMA || pt == Rtsp::PT_PCMU) { - return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved, 1); - } - return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved); - } - case CodecJPEG: return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); - default: WarnL << "暂不支持该CodecId:" << codec_id; return nullptr; +RtpCodec::Ptr Factory::getRtpEncoderByCodecId(CodecId codec, uint8_t pt) { + auto it = s_plugins.find(codec); + if (it == s_plugins.end()) { + WarnL << "Unsupported codec: " << getCodecName(codec); + return nullptr; } + return it->second->getRtpEncoderByCodecId(pt); } -RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) { - // ssrc不冲突即可,可以为任意的32位整形 - static atomic s_ssrc(0); - uint32_t ssrc = s_ssrc++; - if (!ssrc) { - // ssrc不能为0 - ssrc = s_ssrc++; - } - if (sdp->getTrackType() == TrackVideo) { - //视频的ssrc是偶数,方便调试 - ssrc = 2 * ssrc; - } else { - //音频ssrc是奇数 - ssrc = 2 * ssrc + 1; - } - return getRtpEncoderByCodecId(sdp->getCodecId(), sdp->getSampleRate(), sdp->getPayloadType(), ssrc); -} - -RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) { - switch (track->getCodecId()){ - case CodecH264 : return std::make_shared(); - case CodecH265 : return std::make_shared(); - case CodecAAC : return std::make_shared(track->clone()); - case CodecL16 : - case CodecOpus : - case CodecG711A : - case CodecG711U : return std::make_shared(track->getCodecId()); - case CodecJPEG: return std::make_shared(); - default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr; +RtpCodec::Ptr Factory::getRtpDecoderByCodecId(CodecId codec) { + auto it = s_plugins.find(codec); + if (it == s_plugins.end()) { + WarnL << "Unsupported codec: " << getCodecName(codec); + return nullptr; } + return it->second->getRtpDecoderByCodecId(); } /////////////////////////////rtmp相关/////////////////////////////////////////// @@ -196,7 +94,7 @@ static CodecId getVideoCodecIdByAmf(const AMFValue &val){ if (str == "hev1" || str == "hvc1") { return CodecH265; } - WarnL << "暂不支持该视频Amf:" << str; + WarnL << "Unsupported codec: " << str; return CodecInvalid; } @@ -208,23 +106,19 @@ static CodecId getVideoCodecIdByAmf(const AMFValue &val){ case RtmpVideoCodec::h265: return CodecH265; case RtmpVideoCodec::fourcc_av1: return CodecAV1; case RtmpVideoCodec::fourcc_vp9: return CodecVP9; - default: WarnL << "暂不支持该视频Amf:" << (int)type_id; return CodecInvalid; + default: WarnL << "Unsupported codec: " << (int)type_id; return CodecInvalid; } } return CodecInvalid; } -Track::Ptr Factory::getTrackByCodecId(CodecId codecId, int sample_rate, int channels, int sample_bit) { - switch (codecId){ - case CodecH264 : return std::make_shared(); - case CodecH265 : return std::make_shared(); - case CodecAAC : return std::make_shared(); - case CodecOpus: return std::make_shared(); - case CodecG711A : - case CodecG711U : return (sample_rate && channels && sample_bit) ? std::make_shared(codecId, sample_rate, channels, sample_bit) : nullptr; - case CodecJPEG : return std::make_shared(); - default : WarnL << "暂不支持该CodecId:" << codecId; return nullptr; +Track::Ptr Factory::getTrackByCodecId(CodecId codec, int sample_rate, int channels, int sample_bit) { + auto it = s_plugins.find(codec); + if (it == s_plugins.end()) { + WarnL << "Unsupported codec: " << getCodecName(codec); + return nullptr; } + return it->second->getTrackByCodecId(sample_rate, channels, sample_bit); } Track::Ptr Factory::getVideoTrackByAmf(const AMFValue &amf) { @@ -241,7 +135,7 @@ static CodecId getAudioCodecIdByAmf(const AMFValue &val) { if (str == "mp4a") { return CodecAAC; } - WarnL << "暂不支持该音频Amf:" << str; + WarnL << "Unsupported codec: " << str; return CodecInvalid; } @@ -252,7 +146,7 @@ static CodecId getAudioCodecIdByAmf(const AMFValue &val) { case RtmpAudioCodec::g711a : return CodecG711A; case RtmpAudioCodec::g711u : return CodecG711U; case RtmpAudioCodec::opus : return CodecOpus; - default : WarnL << "暂不支持该音频Amf:" << (int)type_id; return CodecInvalid; + default : WarnL << "Unsupported codec: " << (int)type_id; return CodecInvalid; } } @@ -267,43 +161,52 @@ Track::Ptr Factory::getAudioTrackByAmf(const AMFValue& amf, int sample_rate, int return getTrackByCodecId(codecId, sample_rate, channels, sample_bit); } -RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_encode) { - switch (track->getCodecId()){ - case CodecH264 : return std::make_shared(track); - case CodecAAC : return std::make_shared(track); - case CodecH265 : return std::make_shared(track); - case CodecOpus : return std::make_shared(track); - case CodecG711A : - case CodecG711U : { - auto audio_track = dynamic_pointer_cast(track); - if (is_encode && (audio_track->getAudioSampleRate() != 8000 || - audio_track->getAudioChannel() != 1 || - audio_track->getAudioSampleBit() != 16)) { - //rtmp对g711只支持8000/1/16规格,但是ZLMediaKit可以解析其他规格的G711 - WarnL << "RTMP只支持8000/1/16规格的G711,目前规格是:" - << audio_track->getAudioSampleRate() << "/" - << audio_track->getAudioChannel() << "/" - << audio_track->getAudioSampleBit() - << ",该音频已被忽略"; - return nullptr; - } - return std::make_shared(track); - } - default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr; +RtmpCodec::Ptr Factory::getRtmpDecoderByTrack(const Track::Ptr &track) { + auto it = s_plugins.find(track->getCodecId()); + if (it == s_plugins.end()) { + WarnL << "Unsupported codec: " << track->getCodecName(); + return nullptr; } + return it->second->getRtmpDecoderByTrack(track); +} + +RtmpCodec::Ptr Factory::getRtmpEncoderByTrack(const Track::Ptr &track) { + auto it = s_plugins.find(track->getCodecId()); + if (it == s_plugins.end()) { + WarnL << "Unsupported codec: " << track->getCodecName(); + return nullptr; + } + return it->second->getRtmpEncoderByTrack(track); } AMFValue Factory::getAmfByCodecId(CodecId codecId) { + GET_CONFIG(bool, enhanced, Rtmp::kEnhanced); switch (codecId) { case CodecAAC: return AMFValue((int)RtmpAudioCodec::aac); case CodecH264: return AMFValue((int)RtmpVideoCodec::h264); - case CodecH265: return AMFValue((int)RtmpVideoCodec::h265); + case CodecH265: return enhanced ? AMFValue((int)RtmpVideoCodec::fourcc_hevc) : AMFValue((int)RtmpVideoCodec::h265); case CodecG711A: return AMFValue((int)RtmpAudioCodec::g711a); case CodecG711U: return AMFValue((int)RtmpAudioCodec::g711u); case CodecOpus: return AMFValue((int)RtmpAudioCodec::opus); + case CodecAV1: return AMFValue((int)RtmpVideoCodec::fourcc_av1); + case CodecVP9: return AMFValue((int)RtmpVideoCodec::fourcc_vp9); default: return AMFValue(AMF_NULL); } } +Frame::Ptr Factory::getFrameFromPtr(CodecId codec, const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + auto it = s_plugins.find(codec); + if (it == s_plugins.end()) { + WarnL << "Unsupported codec: " << getCodecName(codec); + return nullptr; + } + return it->second->getFrameFromPtr(data, bytes, dts, pts); +} + +Frame::Ptr Factory::getFrameFromBuffer(CodecId codec, Buffer::Ptr data, uint64_t dts, uint64_t pts) { + auto frame = Factory::getFrameFromPtr(codec, data->data(), data->size(), dts, pts); + return std::make_shared(frame, false, std::move(data)); +} + }//namespace mediakit diff --git a/src/Extension/Factory.h b/src/Extension/Factory.h index d0045865..8ec446bc 100644 --- a/src/Extension/Factory.h +++ b/src/Extension/Factory.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -14,13 +14,38 @@ #include #include "Rtmp/amf.h" #include "Extension/Track.h" +#include "Extension/Frame.h" #include "Rtsp/RtpCodec.h" #include "Rtmp/RtmpCodec.h" +#include "Util/onceToken.h" -namespace mediakit{ +#define REGISTER_STATIC_VAR_INNER(var_name, line) var_name##_##line##__ +#define REGISTER_STATIC_VAR(var_name, line) REGISTER_STATIC_VAR_INNER(var_name, line) + +#define REGISTER_CODEC(plugin) \ +static toolkit::onceToken REGISTER_STATIC_VAR(s_token, __LINE__) ([]() { \ + Factory::registerPlugin(plugin); \ +}); + +namespace mediakit { + +struct CodecPlugin { + CodecId (*getCodec)(); + Track::Ptr (*getTrackByCodecId)(int sample_rate, int channels, int sample_bit); + Track::Ptr (*getTrackBySdp)(const SdpTrack::Ptr &track); + RtpCodec::Ptr (*getRtpEncoderByCodecId)(uint8_t pt); + RtpCodec::Ptr (*getRtpDecoderByCodecId)(); + RtmpCodec::Ptr (*getRtmpEncoderByTrack)(const Track::Ptr &track); + RtmpCodec::Ptr (*getRtmpDecoderByTrack)(const Track::Ptr &track); + Frame::Ptr (*getFrameFromPtr)(const char *data, size_t bytes, uint64_t dts, uint64_t pts); +}; class Factory { public: + /** + * 注册插件,非线程安全的 + */ + static void registerPlugin(const CodecPlugin &plugin); /** * 根据codec_id 获取track @@ -42,25 +67,17 @@ public: */ static Track::Ptr getTrackByAbstractTrack(const Track::Ptr& track); - /** - * 根据sdp生成rtp编码器 - * @param sdp sdp对象 - */ - static RtpCodec::Ptr getRtpEncoderBySdp(const Sdp::Ptr &sdp); - /** * 根据codec id生成rtp编码器 * @param codec_id 编码id - * @param sample_rate 采样率,视频固定为90000 * @param pt rtp payload type - * @param ssrc rtp ssrc */ - static RtpCodec::Ptr getRtpEncoderByCodecId(CodecId codec_id, uint32_t sample_rate, uint8_t pt, uint32_t ssrc); + static RtpCodec::Ptr getRtpEncoderByCodecId(CodecId codec_id, uint8_t pt); /** * 根据Track生成Rtp解包器 */ - static RtpCodec::Ptr getRtpDecoderByTrack(const Track::Ptr &track); + static RtpCodec::Ptr getRtpDecoderByCodecId(CodecId codec); ////////////////////////////////rtmp相关////////////////////////////////// @@ -78,16 +95,24 @@ public: static Track::Ptr getAudioTrackByAmf(const AMFValue& amf, int sample_rate, int channels, int sample_bit); /** - * 根据Track获取Rtmp的编解码器 + * 根据Track获取Rtmp的编码器 * @param track 媒体描述对象 - * @param is_encode 是否为编码器还是解码器 */ - static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track, bool is_encode); + static RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track); + + /** + * 根据Track获取Rtmp的解码器 + * @param track 媒体描述对象 + */ + static RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track); /** * 根据codecId获取rtmp的codec描述 */ static AMFValue getAmfByCodecId(CodecId codecId); + + static Frame::Ptr getFrameFromPtr(CodecId codec, const char *data, size_t size, uint64_t dts, uint64_t pts); + static Frame::Ptr getFrameFromBuffer(CodecId codec, toolkit::Buffer::Ptr data, uint64_t dts, uint64_t pts); }; }//namespace mediakit diff --git a/src/Extension/Frame.cpp b/src/Extension/Frame.cpp index 152eea1f..c58ea84b 100644 --- a/src/Extension/Frame.cpp +++ b/src/Extension/Frame.cpp @@ -1,20 +1,26 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "Frame.h" -#include "H264.h" -#include "H265.h" #include "Common/Parser.h" #include "Common/Stamp.h" #include "Common/MediaSource.h" +#if defined(ENABLE_MP4) +#include "mov-format.h" +#endif + +#if defined(ENABLE_HLS) || defined(ENABLE_RTPPROXY) +#include "mpeg-proto.h" +#endif + using namespace std; using namespace toolkit; @@ -34,6 +40,7 @@ Frame::Ptr Frame::getCacheAbleFrame(const Frame::Ptr &frame){ FrameStamp::FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp) { + setIndex(frame->getIndex()); _frame = std::move(frame); // kModifyStampSystem时采用系统时间戳,kModifyStampRelative采用相对时间戳 stamp.revise(_frame->dts(), _frame->pts(), _dts, _pts, modify_stamp == ProtocolOption::kModifyStampSystem); @@ -41,24 +48,73 @@ FrameStamp::FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp) TrackType getTrackType(CodecId codecId) { switch (codecId) { -#define XX(name, type, value, str, mpeg_id) case name : return type; +#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return type; CODEC_MAP(XX) #undef XX default : return TrackInvalid; } } +#if defined(ENABLE_MP4) +int getMovIdByCodec(CodecId codecId) { + switch (codecId) { +#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return mp4_id; + CODEC_MAP(XX) +#undef XX + default : return MOV_OBJECT_NONE; + } +} + +CodecId getCodecByMovId(int object_id) { + if (object_id == MOV_OBJECT_NONE) { + return CodecInvalid; + } + switch (object_id) { +#define XX(name, type, value, str, mpeg_id, mp4_id) case mp4_id : return name; + CODEC_MAP(XX) +#undef XX + default : WarnL << "Unsupported mov: " << object_id; return CodecInvalid; + } +} +#endif + +#if defined(ENABLE_HLS) || defined(ENABLE_RTPPROXY) +int getMpegIdByCodec(CodecId codec) { + switch (codec) { +#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return mpeg_id; + CODEC_MAP(XX) +#undef XX + default : return PSI_STREAM_RESERVED; + } +} + +CodecId getCodecByMpegId(int mpeg_id) { + if (mpeg_id == PSI_STREAM_RESERVED) { + return CodecInvalid; + } + switch (mpeg_id) { +#define XX(name, type, value, str, mpeg_id, mp4_id) case mpeg_id : return name; + CODEC_MAP(XX) +#undef XX + // 海康的 PS 流中会有0xBD 的包 + case 0xBD: return CodecInvalid; + default : WarnL << "Unsupported mpeg: " << mpeg_id; return CodecInvalid; + } +} + +#endif + const char *getCodecName(CodecId codec) { switch (codec) { -#define XX(name, type, value, str, mpeg_id) case name : return str; +#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return str; CODEC_MAP(XX) #undef XX default : return "invalid"; } } -#define XX(name, type, value, str, mpeg_id) {str, name}, -static map codec_map = {CODEC_MAP(XX)}; +#define XX(name, type, value, str, mpeg_id, mp4_id) {str, name}, +static map codec_map = { CODEC_MAP(XX) }; #undef XX CodecId getCodecId(const string &str){ @@ -94,6 +150,10 @@ TrackType CodecInfo::getTrackType() const { return mediakit::getTrackType(getCodecId()); } +std::string CodecInfo::getTrackTypeStr() const { + return getTrackString(getTrackType()); +} + static size_t constexpr kMaxFrameCacheSize = 100; bool FrameMerger::willFlush(const Frame::Ptr &frame) const{ @@ -165,7 +225,19 @@ void FrameMerger::doMerge(BufferLikeString &merged, const Frame::Ptr &frame) con } } +static bool isNeedMerge(CodecId codec){ + switch (codec) { + case CodecH264: + case CodecH265: return true; + default: return false; + } +} + bool FrameMerger::inputFrame(const Frame::Ptr &frame, onOutput cb, BufferLikeString *buffer) { + if (frame && !isNeedMerge(frame->getCodecId())) { + cb(frame->dts(), frame->pts(), frame, true); + return true; + } if (willFlush(frame)) { Frame::Ptr back = _frame_cache.back(); Buffer::Ptr merged_frame = back; @@ -233,8 +305,6 @@ public: */ FrameWriterInterfaceHelper(onWriteFrame cb) { _callback = std::move(cb); } - virtual ~FrameWriterInterfaceHelper() = default; - /** * 写入帧数据 */ diff --git a/src/Extension/Frame.h b/src/Extension/Frame.h index a1b2b6dc..da55e8fe 100644 --- a/src/Extension/Frame.h +++ b/src/Extension/Frame.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,7 +20,9 @@ #include "Network/Buffer.h" namespace mediakit { + class Stamp; + typedef enum { TrackInvalid = -1, TrackVideo = 0, @@ -31,21 +33,21 @@ typedef enum { } TrackType; #define CODEC_MAP(XX) \ - XX(CodecH264, TrackVideo, 0, "H264", PSI_STREAM_H264) \ - XX(CodecH265, TrackVideo, 1, "H265", PSI_STREAM_H265) \ - XX(CodecAAC, TrackAudio, 2, "mpeg4-generic", PSI_STREAM_AAC) \ - XX(CodecG711A, TrackAudio, 3, "PCMA", PSI_STREAM_AUDIO_G711A) \ - XX(CodecG711U, TrackAudio, 4, "PCMU", PSI_STREAM_AUDIO_G711U) \ - XX(CodecOpus, TrackAudio, 5, "opus", PSI_STREAM_AUDIO_OPUS) \ - XX(CodecL16, TrackAudio, 6, "L16", PSI_STREAM_RESERVED) \ - XX(CodecVP8, TrackVideo, 7, "VP8", PSI_STREAM_VP8) \ - XX(CodecVP9, TrackVideo, 8, "VP9", PSI_STREAM_VP9) \ - XX(CodecAV1, TrackVideo, 9, "AV1", PSI_STREAM_AV1) \ - XX(CodecJPEG, TrackVideo, 10, "JPEG", PSI_STREAM_RESERVED) + XX(CodecH264, TrackVideo, 0, "H264", PSI_STREAM_H264, MOV_OBJECT_H264) \ + XX(CodecH265, TrackVideo, 1, "H265", PSI_STREAM_H265, MOV_OBJECT_HEVC) \ + XX(CodecAAC, TrackAudio, 2, "mpeg4-generic", PSI_STREAM_AAC, MOV_OBJECT_AAC) \ + XX(CodecG711A, TrackAudio, 3, "PCMA", PSI_STREAM_AUDIO_G711A, MOV_OBJECT_G711a) \ + XX(CodecG711U, TrackAudio, 4, "PCMU", PSI_STREAM_AUDIO_G711U, MOV_OBJECT_G711u) \ + XX(CodecOpus, TrackAudio, 5, "opus", PSI_STREAM_AUDIO_OPUS, MOV_OBJECT_OPUS) \ + XX(CodecL16, TrackAudio, 6, "L16", PSI_STREAM_RESERVED, MOV_OBJECT_NONE) \ + XX(CodecVP8, TrackVideo, 7, "VP8", PSI_STREAM_VP8, MOV_OBJECT_VP8) \ + XX(CodecVP9, TrackVideo, 8, "VP9", PSI_STREAM_VP9, MOV_OBJECT_VP9) \ + XX(CodecAV1, TrackVideo, 9, "AV1", PSI_STREAM_AV1, MOV_OBJECT_AV1) \ + XX(CodecJPEG, TrackVideo, 10, "JPEG", PSI_STREAM_JPEG_2000, MOV_OBJECT_JPEG) typedef enum { CodecInvalid = -1, -#define XX(name, type, value, str, mpeg_id) name = value, +#define XX(name, type, value, str, mpeg_id, mp4_id) name = value, CODEC_MAP(XX) #undef XX CodecMax @@ -78,6 +80,26 @@ const char *getCodecName(CodecId codecId); */ TrackType getTrackType(CodecId codecId); +/** + * 根据codecid获取mov object id + */ +int getMovIdByCodec(CodecId codecId); + +/** + * 根据mov object id获取CodecId + */ +CodecId getCodecByMovId(int object_id); + +/** + * 根据codecid获取mpeg id + */ +int getMpegIdByCodec(CodecId codec); + +/** + * 根据mpeg id获取CodecId + */ +CodecId getCodecByMpegId(int mpeg_id); + /** * 编码信息的抽象接口 */ @@ -85,7 +107,6 @@ class CodecInfo { public: using Ptr = std::shared_ptr; - CodecInfo() = default; virtual ~CodecInfo() = default; /** @@ -102,6 +123,24 @@ public: * 获取音视频类型 */ TrackType getTrackType() const; + + /** + * 获取音视频类型描述 + */ + std::string getTrackTypeStr() const; + + /** + * 设置track index, 用于支持多track + */ + void setIndex(int index) { _index = index; } + + /** + * 获取track index, 用于支持多track + */ + int getIndex() const { return _index < 0 ? (int)getTrackType() : _index; } + +private: + int _index = -1; }; /** @@ -110,7 +149,6 @@ public: class Frame : public toolkit::Buffer, public CodecInfo { public: using Ptr = std::shared_ptr; - virtual ~Frame() = default; /** * 返回解码时间戳,单位毫秒 @@ -220,24 +258,52 @@ protected: FrameImp() = default; }; -/** - * 一个Frame类中可以有多个帧,他们通过 0x 00 00 01 分隔 - * ZLMediaKit会先把这种复合帧split成单个帧然后再处理 - * 一个复合帧可以通过无内存拷贝的方式切割成多个子Frame - * 提供该类的目的是切割复合帧时防止内存拷贝,提高性能 - */ -template -class FrameInternal : public Parent { +// 包装一个指针成不可缓存的frame +class FrameFromPtr : public Frame { public: - using Ptr = std::shared_ptr; - FrameInternal(const Frame::Ptr &parent_frame, char *ptr, size_t size, size_t prefix_size) - : Parent(ptr, size, parent_frame->dts(), parent_frame->pts(), prefix_size) { - _parent_frame = parent_frame; - } - bool cacheAble() const override { return _parent_frame->cacheAble(); } + using Ptr = std::shared_ptr; -private: - Frame::Ptr _parent_frame; + FrameFromPtr(CodecId codec_id, char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, bool is_key = false) + : FrameFromPtr(ptr, size, dts, pts, prefix_size, is_key) { + _codec_id = codec_id; + } + + char *data() const override { return _ptr; } + size_t size() const override { return _size; } + uint64_t dts() const override { return _dts; } + uint64_t pts() const override { return _pts ? _pts : dts(); } + size_t prefixSize() const override { return _prefix_size; } + bool cacheAble() const override { return false; } + bool keyFrame() const override { return _is_key; } + bool configFrame() const override { return false; } + + CodecId getCodecId() const override { + if (_codec_id == CodecInvalid) { + throw std::invalid_argument("Invalid codec type of FrameFromPtr"); + } + return _codec_id; + } + +protected: + FrameFromPtr() = default; + + FrameFromPtr(char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, bool is_key = false) { + _ptr = ptr; + _size = size; + _dts = dts; + _pts = pts; + _prefix_size = prefix_size; + _is_key = is_key; + } + +protected: + bool _is_key; + char *_ptr; + uint64_t _dts; + uint64_t _pts = 0; + size_t _size; + size_t _prefix_size; + CodecId _codec_id = CodecInvalid; }; /** @@ -247,27 +313,212 @@ private: * 提供该类的目的是切割复合帧时防止内存拷贝,提高性能 */ template -class FrameTSInternal : public Parent { +class FrameInternalBase : public Parent { public: - using Ptr = std::shared_ptr; - FrameTSInternal( - const Frame::Ptr &parent_frame, char *ptr, size_t size, size_t prefix_size, uint64_t dts, uint64_t pts) - : Parent(ptr, size, dts, pts, prefix_size) { - _parent_frame = parent_frame; + using Ptr = std::shared_ptr; + FrameInternalBase(Frame::Ptr parent_frame, char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0) + : Parent(parent_frame->getCodecId(), ptr, size, dts, pts, prefix_size) { + _parent_frame = std::move(parent_frame); + this->setIndex(_parent_frame->getIndex()); } + bool cacheAble() const override { return _parent_frame->cacheAble(); } private: Frame::Ptr _parent_frame; }; +/** + * 一个Frame类中可以有多个帧,他们通过 0x 00 00 01 分隔 + * ZLMediaKit会先把这种复合帧split成单个帧然后再处理 + * 一个复合帧可以通过无内存拷贝的方式切割成多个子Frame + * 提供该类的目的是切割复合帧时防止内存拷贝,提高性能 + */ +template +class FrameInternal : public FrameInternalBase { +public: + using Ptr = std::shared_ptr; + FrameInternal(const Frame::Ptr &parent_frame, char *ptr, size_t size, size_t prefix_size) + : FrameInternalBase(parent_frame, ptr, size, parent_frame->dts(), parent_frame->pts(), prefix_size) {} +}; + +// 管理一个指针生命周期并生产一个frame +class FrameAutoDelete : public FrameFromPtr { +public: + template + FrameAutoDelete(ARGS &&...args) : FrameFromPtr(std::forward(args)...) {} + + ~FrameAutoDelete() override { delete[] _ptr; }; + + bool cacheAble() const override { return true; } +}; + +// 把一个不可缓存的frame声明为可缓存的 +template +class FrameToCache : public Parent { +public: + template + FrameToCache(ARGS &&...args) : Parent(std::forward(args)...) {}; + + bool cacheAble() const override { + return true; + } +}; + +// 该对象的功能是把一个不可缓存的帧转换成可缓存的帧 +class FrameCacheAble : public FrameFromPtr { +public: + using Ptr = std::shared_ptr; + + FrameCacheAble(const Frame::Ptr &frame, bool force_key_frame = false, toolkit::Buffer::Ptr buf = nullptr) { + setIndex(frame->getIndex()); + if (frame->cacheAble()) { + _ptr = frame->data(); + _buffer = frame; + } else if (buf) { + _ptr = frame->data(); + _buffer = std::move(buf); + } else { + auto buffer = std::make_shared(); + buffer->assign(frame->data(), frame->size()); + _ptr = buffer->data(); + _buffer = std::move(buffer); + } + _size = frame->size(); + _dts = frame->dts(); + _pts = frame->pts(); + _prefix_size = frame->prefixSize(); + _codec_id = frame->getCodecId(); + _key = force_key_frame ? true : frame->keyFrame(); + _config = frame->configFrame(); + _drop_able = frame->dropAble(); + _decode_able = frame->decodeAble(); + } + + /** + * 可以被缓存 + */ + bool cacheAble() const override { return true; } + bool keyFrame() const override { return _key; } + bool configFrame() const override { return _config; } + bool dropAble() const override { return _drop_able; } + bool decodeAble() const override { return _decode_able; } + +private: + bool _key; + bool _config; + bool _drop_able; + bool _decode_able; + toolkit::Buffer::Ptr _buffer; +}; + +//该类实现frame级别的时间戳覆盖 +class FrameStamp : public Frame { +public: + using Ptr = std::shared_ptr; + FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp); + ~FrameStamp() override {} + + uint64_t dts() const override { return (uint64_t)_dts; } + uint64_t pts() const override { return (uint64_t)_pts; } + size_t prefixSize() const override { return _frame->prefixSize(); } + bool keyFrame() const override { return _frame->keyFrame(); } + bool configFrame() const override { return _frame->configFrame(); } + bool cacheAble() const override { return _frame->cacheAble(); } + bool dropAble() const override { return _frame->dropAble(); } + bool decodeAble() const override { return _frame->decodeAble(); } + char *data() const override { return _frame->data(); } + size_t size() const override { return _frame->size(); } + CodecId getCodecId() const override { return _frame->getCodecId(); } + +private: + int64_t _dts; + int64_t _pts; + Frame::Ptr _frame; +}; + +/** + * 该对象可以把Buffer对象转换成可缓存的Frame对象 + */ +template +class FrameFromBuffer : public Parent { +public: + /** + * 构造frame + * @param buf 数据缓存 + * @param dts 解码时间戳 + * @param pts 显示时间戳 + * @param prefix 帧前缀长度 + * @param offset buffer有效数据偏移量 + */ + FrameFromBuffer(toolkit::Buffer::Ptr buf, uint64_t dts, uint64_t pts, size_t prefix = 0, size_t offset = 0) + : Parent(buf->data() + offset, buf->size() - offset, dts, pts, prefix) { + _buf = std::move(buf); + } + + /** + * 构造frame + * @param buf 数据缓存 + * @param dts 解码时间戳 + * @param pts 显示时间戳 + * @param prefix 帧前缀长度 + * @param offset buffer有效数据偏移量 + * @param codec 帧类型 + */ + FrameFromBuffer(CodecId codec, toolkit::Buffer::Ptr buf, uint64_t dts, uint64_t pts, size_t prefix = 0, size_t offset = 0) + : Parent(codec, buf->data() + offset, buf->size() - offset, dts, pts, prefix) { + _buf = std::move(buf); + } + + /** + * 该帧可缓存 + */ + bool cacheAble() const override { return true; } + +private: + toolkit::Buffer::Ptr _buf; +}; + +/** + * 合并一些时间戳相同的frame + */ +class FrameMerger { +public: + using onOutput = std::function; + using Ptr = std::shared_ptr; + enum { + none = 0, + h264_prefix, + mp4_nal_size, + }; + + FrameMerger(int type); + + /** + * 刷新输出缓冲,注意此时会调用FrameMerger::inputFrame传入的onOutput回调 + * 请注意回调捕获参数此时是否有效 + */ + void flush(); + void clear(); + bool inputFrame(const Frame::Ptr &frame, onOutput cb, toolkit::BufferLikeString *buffer = nullptr); + +private: + bool willFlush(const Frame::Ptr &frame) const; + void doMerge(toolkit::BufferLikeString &buffer, const Frame::Ptr &frame) const; + +private: + int _type; + bool _have_decode_able_frame = false; + onOutput _cb; + toolkit::List _frame_cache; +}; + /** * 写帧接口的抽象接口类 */ class FrameWriterInterface { public: using Ptr = std::shared_ptr; - FrameWriterInterface() = default; virtual ~FrameWriterInterface() = default; /** @@ -287,8 +538,6 @@ public: class FrameDispatcher : public FrameWriterInterface { public: using Ptr = std::shared_ptr; - FrameDispatcher() = default; - ~FrameDispatcher() override = default; /** * 添加代理 @@ -397,209 +646,5 @@ private: std::map _delegates; }; -/** - * 通过Frame接口包装指针,方便使用者把自己的数据快速接入ZLMediaKit - */ -class FrameFromPtr : public Frame { -public: - using Ptr = std::shared_ptr; - - FrameFromPtr( - CodecId codec_id, char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, - bool is_key = false) - : FrameFromPtr(ptr, size, dts, pts, prefix_size, is_key) { - _codec_id = codec_id; - } - - FrameFromPtr(char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, bool is_key = false) { - _ptr = ptr; - _size = size; - _dts = dts; - _pts = pts; - _prefix_size = prefix_size; - _is_key = is_key; - } - - char *data() const override { return _ptr; } - size_t size() const override { return _size; } - uint64_t dts() const override { return _dts; } - uint64_t pts() const override { return _pts ? _pts : dts(); } - size_t prefixSize() const override { return _prefix_size; } - bool cacheAble() const override { return false; } - bool keyFrame() const override { return _is_key; } - bool configFrame() const override { return false; } - void setCodecId(CodecId codec_id) { _codec_id = codec_id; } - - CodecId getCodecId() const override { - if (_codec_id == CodecInvalid) { - throw std::invalid_argument("FrameFromPtr对象未设置codec类型"); - } - return _codec_id; - } - -protected: - FrameFromPtr() = default; - -protected: - bool _is_key; - char *_ptr; - uint64_t _dts; - uint64_t _pts = 0; - size_t _size; - size_t _prefix_size; - CodecId _codec_id = CodecInvalid; -}; - -/** - * 该对象的功能是把一个不可缓存的帧转换成可缓存的帧 - */ -class FrameCacheAble : public FrameFromPtr { -public: - using Ptr = std::shared_ptr; - - FrameCacheAble(const Frame::Ptr &frame, bool force_key_frame = false) { - if (frame->cacheAble()) { - _frame = frame; - _ptr = frame->data(); - } else { - _buffer = FrameImp::create(); - _buffer->_buffer.assign(frame->data(), frame->size()); - _ptr = _buffer->data(); - } - _size = frame->size(); - _dts = frame->dts(); - _pts = frame->pts(); - _prefix_size = frame->prefixSize(); - _codec_id = frame->getCodecId(); - _key = force_key_frame ? true : frame->keyFrame(); - _config = frame->configFrame(); - _drop_able = frame->dropAble(); - _decode_able = frame->decodeAble(); - } - - ~FrameCacheAble() override = default; - - /** - * 可以被缓存 - */ - bool cacheAble() const override { return true; } - bool keyFrame() const override { return _key; } - bool configFrame() const override { return _config; } - bool dropAble() const override { return _drop_able; } - bool decodeAble() const override { return _decode_able; } - -private: - bool _key; - bool _config; - bool _drop_able; - bool _decode_able; - Frame::Ptr _frame; - FrameImp::Ptr _buffer; -}; - -//该类实现frame级别的时间戳覆盖 -class FrameStamp : public Frame { -public: - using Ptr = std::shared_ptr; - FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp); - ~FrameStamp() override {} - - uint64_t dts() const override { return (uint64_t)_dts; } - uint64_t pts() const override { return (uint64_t)_pts; } - size_t prefixSize() const override { return _frame->prefixSize(); } - bool keyFrame() const override { return _frame->keyFrame(); } - bool configFrame() const override { return _frame->configFrame(); } - bool cacheAble() const override { return _frame->cacheAble(); } - bool dropAble() const override { return _frame->dropAble(); } - bool decodeAble() const override { return _frame->decodeAble(); } - char *data() const override { return _frame->data(); } - size_t size() const override { return _frame->size(); } - CodecId getCodecId() const override { return _frame->getCodecId(); } - -private: - int64_t _dts; - int64_t _pts; - Frame::Ptr _frame; -}; - -/** - * 该对象可以把Buffer对象转换成可缓存的Frame对象 - */ -template -class FrameWrapper : public Parent { -public: - ~FrameWrapper() = default; - - /** - * 构造frame - * @param buf 数据缓存 - * @param dts 解码时间戳 - * @param pts 显示时间戳 - * @param prefix 帧前缀长度 - * @param offset buffer有效数据偏移量 - */ - FrameWrapper(toolkit::Buffer::Ptr buf, uint64_t dts, uint64_t pts, size_t prefix, size_t offset) - : Parent(buf->data() + offset, buf->size() - offset, dts, pts, prefix) { - _buf = std::move(buf); - } - - /** - * 构造frame - * @param buf 数据缓存 - * @param dts 解码时间戳 - * @param pts 显示时间戳 - * @param prefix 帧前缀长度 - * @param offset buffer有效数据偏移量 - * @param codec 帧类型 - */ - FrameWrapper(toolkit::Buffer::Ptr buf, uint64_t dts, uint64_t pts, size_t prefix, size_t offset, CodecId codec) - : Parent(codec, buf->data() + offset, buf->size() - offset, dts, pts, prefix) { - _buf = std::move(buf); - } - - /** - * 该帧可缓存 - */ - bool cacheAble() const override { return true; } - -private: - toolkit::Buffer::Ptr _buf; -}; - -/** - * 合并一些时间戳相同的frame - */ -class FrameMerger { -public: - using onOutput = std::function; - using Ptr = std::shared_ptr; - enum { - none = 0, - h264_prefix, - mp4_nal_size, - }; - - FrameMerger(int type); - ~FrameMerger() = default; - - /** - * 刷新输出缓冲,注意此时会调用FrameMerger::inputFrame传入的onOutput回调 - * 请注意回调捕获参数此时是否有效 - */ - void flush(); - void clear(); - bool inputFrame(const Frame::Ptr &frame, onOutput cb, toolkit::BufferLikeString *buffer = nullptr); - -private: - bool willFlush(const Frame::Ptr &frame) const; - void doMerge(toolkit::BufferLikeString &buffer, const Frame::Ptr &frame) const; - -private: - int _type; - bool _have_decode_able_frame = false; - onOutput _cb; - toolkit::List _frame_cache; -}; - } // namespace mediakit #endif // ZLMEDIAKIT_FRAME_H \ No newline at end of file diff --git a/src/Extension/G711.cpp b/src/Extension/G711.cpp deleted file mode 100644 index 6f505bef..00000000 --- a/src/Extension/G711.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#include "G711.h" - -using namespace std; -using namespace toolkit; - -namespace mediakit{ - -/** - * G711类型SDP - */ -class G711Sdp : public Sdp { -public: - /** - * G711采样率固定为8000 - * @param codecId G711A G711U - * @param sample_rate 音频采样率 - * @param payload_type rtp payload - * @param bitrate 比特率 - */ - G711Sdp(CodecId codecId, - int sample_rate, - int channels, - int bitrate = 128, - int payload_type = 98) : Sdp(sample_rate,payload_type), _codecId(codecId){ - _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; - if (bitrate) { - _printer << "b=AS:" << bitrate << "\r\n"; - } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << sample_rate << "/" << channels << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; - } - - string getSdp() const override { - return _printer; - } - - CodecId getCodecId() const override { - return _codecId; - } -private: - _StrPrinter _printer; - CodecId _codecId; -}; - -Track::Ptr G711Track::clone() { - return std::make_shared::type>(*this); -} - -Sdp::Ptr G711Track::getSdp() { - if(!ready()){ - WarnL << getCodecName() << " Track未准备好"; - return nullptr; - } - - const auto codec = getCodecId(); - const auto sample_rate = getAudioSampleRate(); - const auto audio_channel = getAudioChannel(); - const auto bitrate = getBitRate() >> 10; - auto payload_type = 98; - if (sample_rate == 8000 && audio_channel == 1) { - // https://datatracker.ietf.org/doc/html/rfc3551#section-6 - payload_type = (codec == CodecG711U) ? Rtsp::PT_PCMU : Rtsp::PT_PCMA; - } - - return std::make_shared(codec, sample_rate, audio_channel, bitrate, payload_type); -} - -}//namespace mediakit - - diff --git a/src/Extension/G711Rtp.h b/src/Extension/G711Rtp.h deleted file mode 100644 index ffc8ffe8..00000000 --- a/src/Extension/G711Rtp.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef ZLMEDIAKIT_G711RTP_H -#define ZLMEDIAKIT_G711RTP_H - -#include "Frame.h" -#include "CommonRtp.h" -#include "Rtsp/RtpCodec.h" - -namespace mediakit { - -/** - * G711 rtp编码类 - */ -class G711RtpEncoder : public CommonRtpDecoder, public RtpInfo { -public: - using Ptr = std::shared_ptr; - - ~G711RtpEncoder() override = default; - - /** - * 构造函数 - * @param codec 编码类型 - * @param ssrc ssrc - * @param mtu_size mtu 大小 - * @param sample_rate 采样率 - * @param payload_type pt类型 - * @param interleaved rtsp interleaved 值 - */ - G711RtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, uint32_t sample_rate, uint8_t payload_type, - uint8_t interleaved, uint32_t channels); - - /** - * 输入帧数据并编码成rtp - */ - bool inputFrame(const Frame::Ptr &frame) override; - -private: - uint32_t _channels = 1; - FrameImp::Ptr _cache_frame; -}; - -}//namespace mediakit -#endif //ZLMEDIAKIT_G711RTP_H diff --git a/src/Extension/H264Rtmp.cpp b/src/Extension/H264Rtmp.cpp deleted file mode 100644 index 9e62896d..00000000 --- a/src/Extension/H264Rtmp.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#include "Rtmp/utils.h" -#include "H264Rtmp.h" - -using namespace std; -using namespace toolkit; - -namespace mediakit { - -H264RtmpDecoder::H264RtmpDecoder() { - _h264frame = obtainFrame(); -} - -H264Frame::Ptr H264RtmpDecoder::obtainFrame() { - auto frame = FrameImp::create(); - frame->_prefix_size = 4; - return frame; -} - -/** - * 返回不带0x00 00 00 01头的sps pps - */ -static bool getH264Config(const RtmpPacket &thiz, string &sps, string &pps) { - if ((RtmpVideoCodec)thiz.getRtmpCodecId() != RtmpVideoCodec::h264) { - return false; - } - if (thiz.buffer.size() < 13) { - return false; - } - uint16_t sps_size; - memcpy(&sps_size, thiz.buffer.data() + 11, 2); - sps_size = ntohs(sps_size); - - if ((int) thiz.buffer.size() < 13 + sps_size + 1 + 2) { - return false; - } - uint16_t pps_size; - memcpy(&pps_size, thiz.buffer.data() + 13 + sps_size + 1, 2); - pps_size = ntohs(pps_size); - - if ((int) thiz.buffer.size() < 13 + sps_size + 1 + 2 + pps_size) { - return false; - } - sps.assign(thiz.buffer.data() + 13, sps_size); - pps.assign(thiz.buffer.data() + 13 + sps_size + 1 + 2, pps_size); - return true; -} - -void H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { - if (pkt->isConfigFrame()) { - //缓存sps pps,后续插入到I帧之前 - if (!getH264Config(*pkt, _sps, _pps)) { - WarnL << "get h264 sps/pps failed, rtmp packet is: " << hexdump(pkt->data(), pkt->size()); - return; - } - onGetH264(_sps.data(), _sps.size(), pkt->time_stamp, pkt->time_stamp); - onGetH264(_pps.data(), _pps.size(), pkt->time_stamp, pkt->time_stamp); - return; - } - - if (pkt->buffer.size() > 9) { - auto total_len = pkt->buffer.size(); - size_t offset = 5; - uint8_t *cts_ptr = (uint8_t *) (pkt->buffer.data() + 2); - int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; - auto pts = pkt->time_stamp + cts; - while (offset + 4 < total_len) { - uint32_t frame_len; - memcpy(&frame_len, pkt->buffer.data() + offset, 4); - frame_len = ntohl(frame_len); - offset += 4; - if (frame_len + offset > total_len) { - break; - } - onGetH264(pkt->buffer.data() + offset, frame_len, pkt->time_stamp, pts); - offset += frame_len; - } - } -} - -inline void H264RtmpDecoder::onGetH264(const char* data, size_t len, uint32_t dts, uint32_t pts) { - if (!len) { - return; - } - _h264frame->_dts = dts; - _h264frame->_pts = pts; - _h264frame->_buffer.assign("\x00\x00\x00\x01", 4); //添加264头 - _h264frame->_buffer.append(data, len); - - //写入环形缓存 - RtmpCodec::inputFrame(_h264frame); - _h264frame = obtainFrame(); -} - -//////////////////////////////////////////////////////////////////////// - -H264RtmpEncoder::H264RtmpEncoder(const Track::Ptr &track) { - _track = dynamic_pointer_cast(track); -} - -void H264RtmpEncoder::makeConfigPacket(){ - if (_track && _track->ready()) { - //尝试从track中获取sps pps信息 - _sps = _track->getSps(); - _pps = _track->getPps(); - } - - if (!_sps.empty() && !_pps.empty()) { - //获取到sps/pps - makeVideoConfigPkt(); - _got_config_frame = true; - } -} - -void H264RtmpEncoder::flush() { - inputFrame(nullptr); -} - -bool H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { - if (frame) { - auto data = frame->data() + frame->prefixSize(); - auto len = frame->size() - frame->prefixSize(); - auto type = H264_TYPE(data[0]); - switch (type) { - case H264Frame::NAL_SPS: { - if (!_got_config_frame) { - _sps = string(data, len); - makeConfigPacket(); - } - break; - } - case H264Frame::NAL_PPS: { - if (!_got_config_frame) { - _pps = string(data, len); - makeConfigPacket(); - } - break; - } - default: break; - } - } - - if (!_rtmp_packet) { - _rtmp_packet = RtmpPacket::create(); - //flags/not config/cts预占位 - _rtmp_packet->buffer.resize(5); - } - - return _merger.inputFrame(frame, [this](uint64_t dts, uint64_t pts, const Buffer::Ptr &, bool have_key_frame) { - // flags - _rtmp_packet->buffer[0] = (uint8_t)RtmpVideoCodec::h264 | ((uint8_t)(have_key_frame ? RtmpFrameType::key_frame : RtmpFrameType::inter_frame) << 4); - _rtmp_packet->buffer[1] = (uint8_t)RtmpH264PacketType::h264_nalu; - int32_t cts = pts - dts; - // cts - set_be24(&_rtmp_packet->buffer[2], cts); - _rtmp_packet->time_stamp = dts; - _rtmp_packet->body_size = _rtmp_packet->buffer.size(); - _rtmp_packet->chunk_id = CHUNK_VIDEO; - _rtmp_packet->stream_index = STREAM_MEDIA; - _rtmp_packet->type_id = MSG_VIDEO; - // 输出rtmp packet - RtmpCodec::inputRtmp(_rtmp_packet); - _rtmp_packet = nullptr; - }, &_rtmp_packet->buffer); -} - -void H264RtmpEncoder::makeVideoConfigPkt() { - if (_sps.size() < 4) { - WarnL << "sps长度不足4字节"; - return; - } - auto flags = (uint8_t)RtmpVideoCodec::h264; - flags |= ((uint8_t)RtmpFrameType::key_frame << 4); - auto pkt = RtmpPacket::create(); - // header - pkt->buffer.push_back(flags); - pkt->buffer.push_back((uint8_t)RtmpH264PacketType::h264_config_header); - // cts - pkt->buffer.append("\x0\x0\x0", 3); - // AVCDecoderConfigurationRecord start - pkt->buffer.push_back(1); // version - pkt->buffer.push_back(_sps[1]); // profile - pkt->buffer.push_back(_sps[2]); // compat - pkt->buffer.push_back(_sps[3]); // level - pkt->buffer.push_back((char)0xff); // 6 bits reserved + 2 bits nal size length - 1 (11) - pkt->buffer.push_back((char)0xe1); // 3 bits reserved + 5 bits number of sps (00001) - // sps - uint16_t size = (uint16_t)_sps.size(); - size = htons(size); - pkt->buffer.append((char *)&size, 2); - pkt->buffer.append(_sps); - // pps - pkt->buffer.push_back(1); // version - size = (uint16_t)_pps.size(); - size = htons(size); - pkt->buffer.append((char *)&size, 2); - pkt->buffer.append(_pps); - - pkt->body_size = pkt->buffer.size(); - pkt->chunk_id = CHUNK_VIDEO; - pkt->stream_index = STREAM_MEDIA; - pkt->time_stamp = 0; - pkt->type_id = MSG_VIDEO; - RtmpCodec::inputRtmp(pkt); -} - -}//namespace mediakit diff --git a/src/Extension/H265Rtmp.cpp b/src/Extension/H265Rtmp.cpp deleted file mode 100644 index af685d36..00000000 --- a/src/Extension/H265Rtmp.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#include "Rtmp/utils.h" -#include "H265Rtmp.h" -#ifdef ENABLE_MP4 -#include "mpeg4-hevc.h" -#endif // ENABLE_MP4 - -using namespace std; -using namespace toolkit; - -namespace mediakit { - -H265RtmpDecoder::H265RtmpDecoder() { - _h265frame = obtainFrame(); -} - -H265Frame::Ptr H265RtmpDecoder::obtainFrame() { - auto frame = FrameImp::create(); - frame->_prefix_size = 4; - return frame; -} - -#ifdef ENABLE_MP4 - -static bool decode_HEVCDecoderConfigurationRecord(uint8_t *extra, size_t bytes, string &frame) { - struct mpeg4_hevc_t hevc; - memset(&hevc, 0, sizeof(hevc)); - if (mpeg4_hevc_decoder_configuration_record_load((uint8_t *)extra, bytes, &hevc) > 0) { - uint8_t *config = new uint8_t[bytes * 2]; - int size = mpeg4_hevc_to_nalu(&hevc, config, bytes * 2); - if (size > 4) { - frame.assign((char *)config + 4, size - 4); - } - delete[] config; - return size > 4; - } - return false; -} - -/** - * 返回不带0x00 00 00 01头的sps - */ -static bool getH265ConfigFrame(const RtmpPacket &thiz, string &frame) { - if ((RtmpVideoCodec)thiz.getRtmpCodecId() != RtmpVideoCodec::h265) { - return false; - } - if (thiz.buffer.size() < 6) { - WarnL << "bad H265 cfg!"; - return false; - } - return decode_HEVCDecoderConfigurationRecord((uint8_t *)thiz.buffer.data() + 5, thiz.buffer.size() - 5, frame); -} -#endif - -void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { - if (_info.codec == CodecInvalid) { - // 先判断是否为增强型rtmp - parseVideoRtmpPacket((uint8_t *)pkt->data(), pkt->size(), &_info); - } - - if (_info.is_enhanced) { - // 增强型rtmp - parseVideoRtmpPacket((uint8_t *)pkt->data(), pkt->size(), &_info); - if (!_info.is_enhanced || _info.codec != CodecH265) { - throw std::invalid_argument("Invalid enhanced-rtmp hevc packet!"); - } - auto data = (uint8_t *)pkt->data() + 5; - auto size = pkt->size() - 5; - switch (_info.video.pkt_type) { - case RtmpPacketType::PacketTypeSequenceStart: { -#ifdef ENABLE_MP4 - string config; - if (decode_HEVCDecoderConfigurationRecord(data, size, config)) { - onGetH265(config.data(), config.size(), pkt->time_stamp, pkt->time_stamp); - } -#else - WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265-RTMP支持不完善"; -#endif - break; - } - - case RtmpPacketType::PacketTypeCodedFramesX: - case RtmpPacketType::PacketTypeCodedFrames: { - auto pts = pkt->time_stamp; - if (RtmpPacketType::PacketTypeCodedFrames == _info.video.pkt_type) { - // SI24 = [CompositionTime Offset] - CHECK(size > 7); - int32_t cts = (((data[0] << 16) | (data[1] << 8) | (data[2])) + 0xff800000) ^ 0xff800000; - pts += cts; - data += 3; - size -= 3; - } - splitFrame(data, size, pkt->time_stamp, pts); - break; - } - - case RtmpPacketType::PacketTypeMetadata: { - // The body does not contain video data. The body is an AMF encoded metadata. - // The metadata will be represented by a series of [name, value] pairs. - // For now the only defined [name, value] pair is [“colorInfo”, Object] - // See Metadata Frame section for more details of this object. - // - // For a deeper understanding of the encoding please see description - // of SCRIPTDATA and SSCRIPTDATAVALUE in the FLV file spec. - // DATA = [“colorInfo”, Object] - break; - } - case RtmpPacketType::PacketTypeSequenceEnd: { - // signals end of sequence - break; - } - default: break; - } - return; - } - - // 国内扩展(12) H265 rtmp - if (pkt->isConfigFrame()) { -#ifdef ENABLE_MP4 - string config; - if (getH265ConfigFrame(*pkt, config)) { - onGetH265(config.data(), config.size(), pkt->time_stamp, pkt->time_stamp); - } -#else - WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265-RTMP支持不完善"; -#endif - return; - } - - if (pkt->buffer.size() > 9) { - uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2); - int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; - auto pts = pkt->time_stamp + cts; - splitFrame((uint8_t *)pkt->data() + 5, pkt->size() - 5, pkt->time_stamp, pts); - } -} - -void H265RtmpDecoder::splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts) { - auto end = data + size; - while (data + 4 < end) { - uint32_t frame_len = load_be32(data); - data += 4; - if (data + frame_len > end) { - break; - } - onGetH265((const char *)data, frame_len, dts, pts); - data += frame_len; - } -} - -inline void H265RtmpDecoder::onGetH265(const char *data, size_t size, uint32_t dts, uint32_t pts) { - if (size == 0) { - return; - } -#if 1 - _h265frame->_dts = dts; - _h265frame->_pts = pts; - _h265frame->_buffer.assign("\x00\x00\x00\x01", 4); // 添加265头 - _h265frame->_buffer.append(data, size); - - // 写入环形缓存 - RtmpCodec::inputFrame(_h265frame); - _h265frame = obtainFrame(); -#else - // 防止内存拷贝,这样产生的265帧不会有0x00 00 01头 - auto frame = std::make_shared((char *)data, size, dts, pts, 0); - RtmpCodec::inputFrame(frame); -#endif -} - -//////////////////////////////////////////////////////////////////////// - -H265RtmpEncoder::H265RtmpEncoder(const Track::Ptr &track) { - _track = dynamic_pointer_cast(track); -} - -void H265RtmpEncoder::makeConfigPacket() { - if (_track && _track->ready()) { - // 尝试从track中获取sps pps信息 - _sps = _track->getSps(); - _pps = _track->getPps(); - _vps = _track->getVps(); - } - - if (!_sps.empty() && !_pps.empty() && !_vps.empty()) { - // 获取到sps/pps - makeVideoConfigPkt(); - _got_config_frame = true; - } -} - -void H265RtmpEncoder::flush() { - inputFrame(nullptr); -} - -bool H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) { - if (frame) { - auto data = frame->data() + frame->prefixSize(); - auto len = frame->size() - frame->prefixSize(); - auto type = H265_TYPE(data[0]); - switch (type) { - case H265Frame::NAL_SPS: { - if (!_got_config_frame) { - _sps = string(data, len); - makeConfigPacket(); - } - break; - } - case H265Frame::NAL_PPS: { - if (!_got_config_frame) { - _pps = string(data, len); - makeConfigPacket(); - } - break; - } - case H265Frame::NAL_VPS: { - if (!_got_config_frame) { - _vps = string(data, len); - makeConfigPacket(); - } - break; - } - default: break; - } - } - - if (!_rtmp_packet) { - _rtmp_packet = RtmpPacket::create(); - // flags/not_config/cts预占位 - _rtmp_packet->buffer.resize(5); - } - - return _merger.inputFrame(frame, [this](uint64_t dts, uint64_t pts, const Buffer::Ptr &, bool have_key_frame) { - // flags - _rtmp_packet->buffer[0] = (uint8_t)RtmpVideoCodec::h265 | ((uint8_t)(have_key_frame ? RtmpFrameType::key_frame : RtmpFrameType::inter_frame) << 4); - _rtmp_packet->buffer[1] = (uint8_t)RtmpH264PacketType::h264_nalu; - int32_t cts = pts - dts; - // cts - set_be24(&_rtmp_packet->buffer[2], cts); - _rtmp_packet->time_stamp = dts; - _rtmp_packet->body_size = _rtmp_packet->buffer.size(); - _rtmp_packet->chunk_id = CHUNK_VIDEO; - _rtmp_packet->stream_index = STREAM_MEDIA; - _rtmp_packet->type_id = MSG_VIDEO; - // 输出rtmp packet - RtmpCodec::inputRtmp(_rtmp_packet); - _rtmp_packet = nullptr; - }, &_rtmp_packet->buffer); -} - -void H265RtmpEncoder::makeVideoConfigPkt() { -#ifdef ENABLE_MP4 - auto flags = (uint8_t)RtmpVideoCodec::h265; - flags |= ((uint8_t)RtmpFrameType::key_frame << 4); - auto pkt = RtmpPacket::create(); - // header - pkt->buffer.push_back(flags); - pkt->buffer.push_back((uint8_t)RtmpH264PacketType::h264_config_header); - // cts - pkt->buffer.append("\x0\x0\x0", 3); - - struct mpeg4_hevc_t hevc; - memset(&hevc, 0, sizeof(hevc)); - string vps_sps_pps = string("\x00\x00\x00\x01", 4) + _vps + string("\x00\x00\x00\x01", 4) + _sps + string("\x00\x00\x00\x01", 4) + _pps; - h265_annexbtomp4(&hevc, vps_sps_pps.data(), (int)vps_sps_pps.size(), NULL, 0, NULL, NULL); - uint8_t extra_data[1024]; - int extra_data_size = mpeg4_hevc_decoder_configuration_record_save(&hevc, extra_data, sizeof(extra_data)); - if (extra_data_size == -1) { - WarnL << "生成H265 extra_data 失败"; - return; - } - // HEVCDecoderConfigurationRecord - pkt->buffer.append((char *)extra_data, extra_data_size); - pkt->body_size = pkt->buffer.size(); - pkt->chunk_id = CHUNK_VIDEO; - pkt->stream_index = STREAM_MEDIA; - pkt->time_stamp = 0; - pkt->type_id = MSG_VIDEO; - RtmpCodec::inputRtmp(pkt); -#else - WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265-RTMP支持不完善"; -#endif -} - -} // namespace mediakit diff --git a/src/Extension/JPEG.cpp b/src/Extension/JPEG.cpp deleted file mode 100644 index de024a03..00000000 --- a/src/Extension/JPEG.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "JPEG.h" -#include "Rtsp/Rtsp.h" -#include "Util/util.h" - -using namespace toolkit; - -namespace mediakit { - -bool JPEGTrack::inputFrame(const Frame::Ptr &frame) { - if (!ready()) { - if (_height > 0 && _width > 0) { - if (_tmp == 0) _tmp = frame->dts(); - else _fps = 1000.0 / (frame->dts() - _tmp); - } else getVideoResolution((uint8_t*)frame->data(), frame->size()); - return false; - } - return VideoTrack::inputFrame(frame); -} - -void JPEGTrack::getVideoResolution(const uint8_t *buf, int len) { - for (int i = 0; i < len - 8; i++) { - if (buf[i] != 0xff) - continue; - if (buf[i + 1] == 0xC0 /*SOF0*/) { - _height = buf[i + 5] * 256 + buf[i + 6]; - _width = buf[i + 7] * 256 + buf[i + 8]; - return; - } - } -} - -class JPEGSdp : public Sdp { -public: - JPEGSdp(int bitrate): Sdp(90000, Rtsp::PT_JPEG) { - _printer << "m=video 0 RTP/AVP " << (int)getPayloadType() << "\r\n"; - if (bitrate) { - _printer << "b=AS:" << bitrate << "\r\n"; - } - _printer << "a=control:trackID=" << (int)TrackVideo << "\r\n"; - } - - std::string getSdp() const { return _printer; } - - CodecId getCodecId() const { return CodecJPEG; } - -private: - _StrPrinter _printer; -}; - -Sdp::Ptr JPEGTrack::getSdp() { - return std::make_shared(getBitRate() / 1024); -} -} // namespace mediakit diff --git a/src/Extension/L16.cpp b/src/Extension/L16.cpp deleted file mode 100644 index dff70a2e..00000000 --- a/src/Extension/L16.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#include "L16.h" - -using namespace std; -using namespace toolkit; - -namespace mediakit{ - -/** - * L16类型SDP - */ -class L16Sdp : public Sdp { -public: - /** - * L16采样位数固定为16位 - * @param codecId CodecL16 - * @param sample_rate 音频采样率 - * @param payload_type rtp payload - * @param bitrate 比特率 - */ - L16Sdp(CodecId codecId, - int sample_rate, - int channels, - int bitrate = 128, - int payload_type = 98) : Sdp(sample_rate,payload_type), _codecId(codecId){ - _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; - if (bitrate) { - _printer << "b=AS:" << bitrate << "\r\n"; - } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << sample_rate << "/" << channels << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; - } - - string getSdp() const override { - return _printer; - } - - CodecId getCodecId() const override { - return _codecId; - } -private: - _StrPrinter _printer; - CodecId _codecId; -}; - -Sdp::Ptr L16Track::getSdp() { - WarnL << "Enter L16Track::getSdp function"; - if(!ready()){ - WarnL << getCodecName() << " Track未准备好"; - return nullptr; - } - return std::make_shared(getCodecId(), getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); -} - -Track::Ptr L16Track::clone() { - return std::make_shared::type >(*this); -} - -}//namespace mediakit - - diff --git a/src/Extension/Opus.cpp b/src/Extension/Opus.cpp deleted file mode 100644 index 0e0100a2..00000000 --- a/src/Extension/Opus.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. - * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). - * - * Use of this source code is governed by MIT license that can be found in the - * LICENSE file in the root of the source tree. All contributing project authors - * may be found in the AUTHORS file in the root of the source tree. - */ - -#include "Opus.h" - -using namespace std; -using namespace toolkit; - -namespace mediakit{ - -/** - * Opus类型SDP - */ -class OpusSdp : public Sdp { -public: - /** - * 构造opus sdp - * @param sample_rate 音频采样率 - * @param payload_type rtp payload - * @param bitrate 比特率 - */ - OpusSdp(int sample_rate, - int channels, - int bitrate = 128, - int payload_type = 98) : Sdp(sample_rate,payload_type){ - _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; - if (bitrate) { - _printer << "b=AS:" << bitrate << "\r\n"; - } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << sample_rate << "/" << channels << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; - } - - string getSdp() const override { - return _printer; - } - - CodecId getCodecId() const override { - return CodecOpus; - } -private: - _StrPrinter _printer; -}; - -Sdp::Ptr OpusTrack::getSdp() { - if(!ready()){ - WarnL << getCodecName() << " Track未准备好"; - return nullptr; - } - return std::make_shared(getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); -} - -}//namespace mediakit \ No newline at end of file diff --git a/src/Extension/Track.h b/src/Extension/Track.h index 3a1b8519..8264b3a8 100644 --- a/src/Extension/Track.h +++ b/src/Extension/Track.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -21,23 +21,35 @@ namespace mediakit{ /** * 媒体通道描述类,也支持帧输入输出 */ -class Track : public FrameDispatcher , public CodecInfo{ +class Track : public FrameDispatcher, public CodecInfo { public: using Ptr = std::shared_ptr; + + /** + * 默认构造 + */ Track() = default; - virtual ~Track() = default; + + /** + * 复制拷贝,只能拷贝派生类的信息, + * 环形缓存和代理关系不能拷贝,否则会关系紊乱 + */ + Track(const Track &that) { + _bit_rate = that._bit_rate; + setIndex(that.getIndex()); + } /** * 是否准备好,准备好才能获取譬如sps pps等信息 */ - virtual bool ready() = 0; + virtual bool ready() const = 0; /** * 克隆接口,用于复制本对象用 * 在调用该接口时只会复制派生类的信息 * 环形缓存和代理关系不能拷贝,否则会关系紊乱 */ - virtual Track::Ptr clone() = 0; + virtual Track::Ptr clone() const = 0; /** * 更新track信息,比如触发sps/pps解析 @@ -46,9 +58,19 @@ public: /** * 生成sdp - * @return sdp对象 + * @return sdp对象 */ - virtual Sdp::Ptr getSdp() = 0; + virtual Sdp::Ptr getSdp(uint8_t payload_type) const = 0; + + /** + * 获取extra data, 一般用于rtmp/mp4生成 + */ + virtual toolkit::Buffer::Ptr getExtraData() const { return nullptr; } + + /** + * 设置extra data, + */ + virtual void setExtraData(const uint8_t *data, size_t size) {} /** * 返回比特率 @@ -62,14 +84,6 @@ public: */ virtual void setBitRate(int bit_rate) { _bit_rate = bit_rate; } - /** - * 复制拷贝,只能拷贝派生类的信息, - * 环形缓存和代理关系不能拷贝,否则会关系紊乱 - */ - Track(const Track &that){ - _bit_rate = that._bit_rate; - } - private: int _bit_rate = 0; }; @@ -97,6 +111,40 @@ public: virtual float getVideoFps() const { return 0; } }; +class VideoTrackImp : public VideoTrack { +public: + using Ptr = std::shared_ptr; + + /** + * 构造函数 + * @param codec_id 编码类型 + * @param width 宽 + * @param height 高 + * @param fps 帧率 + */ + VideoTrackImp(CodecId codec_id, int width, int height, int fps) { + _codec_id = codec_id; + _width = width; + _height = height; + _fps = fps; + } + + int getVideoHeight() const override { return _width; } + int getVideoWidth() const override { return _height; } + float getVideoFps() const override { return _fps; } + bool ready() const override { return true; } + + Track::Ptr clone() const override { return std::make_shared(*this); } + Sdp::Ptr getSdp(uint8_t payload_type) const override { return nullptr; } + CodecId getCodecId() const override { return _codec_id; } + +private: + CodecId _codec_id; + int _width = 0; + int _height = 0; + float _fps = 0; +}; + /** * 音频Track派生类,支持采样率通道数,采用位数信息 */ @@ -131,7 +179,7 @@ public: * @param channels 通道数 * @param sample_bit 采样位数,一般为16 */ - AudioTrackImp(CodecId codecId,int sample_rate, int channels, int sample_bit){ + AudioTrackImp(CodecId codecId, int sample_rate, int channels, int sample_bit){ _codecid = codecId; _sample_rate = sample_rate; _channels = channels; @@ -148,7 +196,7 @@ public: /** * 是否已经初始化 */ - bool ready() override { + bool ready() const override { return true; } @@ -172,6 +220,10 @@ public: int getAudioChannel() const override{ return _channels; } + + Track::Ptr clone() const override { return std::make_shared(*this); } + Sdp::Ptr getSdp(uint8_t payload_type) const override { return nullptr; } + private: CodecId _codecid; int _sample_rate; @@ -179,9 +231,8 @@ private: int _sample_bit; }; -class TrackSource{ +class TrackSource { public: - TrackSource() = default; virtual ~TrackSource() = default; /** diff --git a/src/FMP4/FMP4MediaSource.h b/src/FMP4/FMP4MediaSource.h index 13674ebe..55ab1a70 100644 --- a/src/FMP4/FMP4MediaSource.h +++ b/src/FMP4/FMP4MediaSource.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -26,7 +26,6 @@ public: template FMP4Packet(ARGS && ...args) : toolkit::BufferString(std::forward(args)...) {}; - ~FMP4Packet() override = default; public: uint64_t time_stamp = 0; diff --git a/src/FMP4/FMP4MediaSourceMuxer.h b/src/FMP4/FMP4MediaSourceMuxer.h index 314951c9..2725531e 100644 --- a/src/FMP4/FMP4MediaSourceMuxer.h +++ b/src/FMP4/FMP4MediaSourceMuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HlsParser.cpp b/src/Http/HlsParser.cpp index 5cbd9195..c92a81d0 100644 --- a/src/Http/HlsParser.cpp +++ b/src/Http/HlsParser.cpp @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HlsParser.h b/src/Http/HlsParser.h index c54fc6e5..e61540e7 100644 --- a/src/Http/HlsParser.h +++ b/src/Http/HlsParser.h @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -36,9 +36,6 @@ typedef struct{ class HlsParser { public: - HlsParser() = default; - ~HlsParser() = default; - bool parse(const std::string &http_url,const std::string &m3u8); /** diff --git a/src/Http/HlsPlayer.cpp b/src/Http/HlsPlayer.cpp index 3e27a012..aeb74c65 100644 --- a/src/Http/HlsPlayer.cpp +++ b/src/Http/HlsPlayer.cpp @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -23,6 +23,7 @@ void HlsPlayer::play(const string &url) { _play_result = false; _play_url = url; setProxyUrl((*this)[Client::kProxyUrl]); + setAllowResendRequest(true); fetchIndexFile(); } @@ -43,17 +44,24 @@ void HlsPlayer::teardown_l(const SockException &ex) { _play_result = true; onPlayResult(ex); } else { - //如果不是主动关闭的,则重新拉取索引文件 - if (ex.getErrCode() != Err_shutdown) { - // 当切片列表已空, 且没有正在下载的切片并且重试次数已经达到最大次数时, 则认为失败关闭播放器 - if (_ts_list.empty() && !(_http_ts_player && _http_ts_player->waitResponse()) - && _try_fetch_index_times >= MAX_TRY_FETCH_INDEX_TIMES) { + // 如果不是主动关闭的,则重新拉取索引文件 + // if not actively closed, re-fetch the index file + if (ex.getErrCode() != Err_shutdown && HlsParser::isLive()) { + // 如果重试次数已经达到最大次数时, 且切片列表已空, 而且没有正在下载的切片, 则认为失败关闭播放器 + // If the retry count has reached the maximum number of times, and the segments list is empty, and there is no segment being downloaded, + // the player is considered to be closed due to failure + if (_ts_list.empty() && !(_http_ts_player && _http_ts_player->waitResponse()) && _try_fetch_index_times >= MAX_TRY_FETCH_INDEX_TIMES) { onShutdown(ex); } else { _try_fetch_index_times += 1; shutdown(ex); WarnL << "Attempt to pull the m3u8 file again[" << _try_fetch_index_times << "]:" << _play_url; - fetchIndexFile(); + // 当网络波动时有可能拉取m3u8文件失败, 因此快速重试拉取m3u8文件, 而不是直接关闭播放器 + // 这里增加一个延时是为了防止_http_ts_player的socket还保持alive状态,就多次拉取m3u8文件了 + // When the network fluctuates, it is possible to fail to pull the m3u8 file, so quickly retry to pull the m3u8 file instead of closing the player directly + // The delay here is to prevent the socket of _http_ts_player from still keeping alive state, and pull the m3u8 file multiple times + //todo _http_ts_player->waitResponse()这个判断条件是否有必要?因为有时候存在_complete==true,但是_http_ts_player->alive()为true的情况 + playDelay(0.3); return; } } else { @@ -73,23 +81,26 @@ void HlsPlayer::teardown() { void HlsPlayer::fetchSegment() { if (_ts_list.empty()) { // 如果是点播文件,播放列表为空代表文件播放结束,关闭播放器: #2628 - if(!HlsParser::isLive()){ + // If it is a video-on-demand file, the playlist is empty means the file is finished playing, close the player: #2628 + if (!HlsParser::isLive()) { teardown(); return; } - //播放列表为空,那么立即重新下载m3u8文件 + // 播放列表为空,那么立即重新下载m3u8文件 + // The playlist is empty, so download the m3u8 file immediately _timer.reset(); fetchIndexFile(); return; } if (_http_ts_player && _http_ts_player->waitResponse()) { - //播放器目前还存活,正在下载中 + // 播放器目前还存活,正在下载中 return; } weak_ptr weak_self = static_pointer_cast(shared_from_this()); if (!_http_ts_player) { _http_ts_player = std::make_shared(getPoller()); _http_ts_player->setProxyUrl((*this)[Client::kProxyUrl]); + _http_ts_player->setAllowResendRequest(true); _http_ts_player->setOnCreateSocket([weak_self](const EventPoller::Ptr &poller) { auto strong_self = weak_self.lock(); if (strong_self) { @@ -104,7 +115,8 @@ void HlsPlayer::fetchSegment() { if (!strong_self) { return; } - //收到ts包 + // 收到ts包 + // Received ts package strong_self->onPacket(data, len); }); } @@ -131,14 +143,25 @@ void HlsPlayer::fetchSegment() { } else { strong_self->_timeout_multiple = MAX(strong_self->_timeout_multiple - 1, MIN_TIMEOUT_MULTIPLE); } + strong_self->_ts_download_failed_count++; + if (strong_self->_ts_download_failed_count > MAX_TS_DOWNLOAD_FAILED_COUNT) { + WarnL << "ts segment " << url << " download failed count is " << strong_self->_ts_download_failed_count << ", teardown player"; + strong_self->teardown_l(SockException(Err_shutdown, "ts segment download failed")); + return; + } + } else { + strong_self->_ts_download_failed_count = 0; } // 提前0.5秒下载好,支持点播文件控制下载速度: #2628 + // Download 0.5 seconds in advance to support video-on-demand files to control download speed: #2628 auto delay = duration - 0.5 - ticker.elapsedTime() / 1000.0f; if (delay > 2.0) { // 提前1秒下载 + // Download 1 second in advance delay -= 1.0; } else if (delay <= 0) { // 延时最小10ms + // Delay at least 10ms delay = 0.01; } // 延时下载下一个切片 @@ -152,7 +175,8 @@ void HlsPlayer::fetchSegment() { }); _http_ts_player->setMethod("GET"); - //ts切片必须在其时长的2-5倍内下载完毕 + // ts切片必须在其时长的2-5倍内下载完毕 + // The ts segment must be downloaded within 2-5 times its duration _http_ts_player->setCompleteTimeout(_timeout_multiple * duration * 1000); _http_ts_player->sendRequest(url); } @@ -160,10 +184,14 @@ void HlsPlayer::fetchSegment() { bool HlsPlayer::onParsed(bool is_m3u8_inner, int64_t sequence, const map &ts_map) { if (!is_m3u8_inner) { // 这是ts播放列表 + // This is the ts playlist if (_last_sequence == sequence) { // 如果是重复的ts列表,那么忽略 // 但是需要注意, 如果当前ts列表为空了, 那么表明直播结束了或者m3u8文件有问题,需要重新拉流 // 这里的5倍是为了防止m3u8文件有问题导致的无限重试 + // If it is a duplicate ts list, ignore it + // But it should be noted that if the current ts list is empty, it means that the live broadcast is over or the m3u8 file is problematic, and you need to re-pull the stream + // The 5 times here is to prevent infinite retries caused by problems with the m3u8 file if (_last_sequence > 0 && _ts_list.empty() && HlsParser::isLive() && _wait_index_update_ticker.elapsedTime() > (uint64_t)HlsParser::getTargetDur() * 1000 * 5) { _wait_index_update_ticker.resetTime(); @@ -179,19 +207,23 @@ bool HlsPlayer::onParsed(bool is_m3u8_inner, int64_t sequence, const map 2 * ts_map.size()) { // 去除防重列表中过多的数据 + // Remove too much data from the anti-repetition list _ts_url_cache.erase(_ts_url_sort.front()); _ts_url_sort.pop_front(); } fetchSegment(); } else { // 这是m3u8列表,我们播放最高清的子hls + // This is the m3u8 list, we play the highest quality sub-hls if (ts_map.empty()) { throw invalid_argument("empty sub hls list:" + getUrl()); } @@ -210,7 +242,8 @@ bool HlsPlayer::onParsed(bool is_m3u8_inner, int64_t sequence, const map(headers)["Content-Type"]); @@ -233,6 +266,11 @@ void HlsPlayer::onResponseCompleted(const SockException &ex) { teardown_l(SockException(Err_other, "parse m3u8 failed:" + _play_url)); return; } + // 如果有或取到新的切片, 那么就算成功, 应该重置失败次数 + // if there are new segments or get new segments, it is considered successful, and the number of failures should be reset + if (!_ts_list.empty()) { + _try_fetch_index_times = 0; + } if (!_play_result) { _play_result = true; onPlayResult(SockException()); @@ -246,16 +284,21 @@ float HlsPlayer::delaySecond() { if (HlsParser::isLive()) { // see RFC 8216, Section 4.4.3.8. // 根据rfc刷新index列表的周期应该是分段时间x3, 因为根据规范播放器只处理最后3个Segment - targetOffset = (float) (3 * HlsParser::getTargetDur()); + // refresh the index list according to rfc cycle should be the segment time x3, + // because according to the specification, the player only handles the last 3 segments + targetOffset = (float)(3 * HlsParser::getTargetDur()); } else { // 点播则一般m3u8文件不会在改变了, 没必要频繁的刷新, 所以按照总时间来进行刷新 + // On-demand, the m3u8 file will generally not change, so there is no need to refresh frequently, targetOffset = HlsParser::getTotalDuration(); } // 取最小值, 避免因为分段时长不规则而导致的问题 + // Take the minimum value to avoid problems caused by irregular segment duration if (targetOffset > HlsParser::getTotalDuration()) { targetOffset = HlsParser::getTotalDuration(); } // 根据规范为一半的时间 + // According to the specification, it is half the time if (targetOffset / 2 > 1.0f) { return targetOffset / 2; } @@ -268,15 +311,18 @@ bool HlsPlayer::onRedirectUrl(const string &url, bool temporary) { return true; } -void HlsPlayer::playDelay() { +void HlsPlayer::playDelay(float delay_sec) { weak_ptr weak_self = static_pointer_cast(shared_from_this()); - _timer.reset(new Timer(delaySecond(), [weak_self]() { - auto strong_self = weak_self.lock(); - if (strong_self) { - strong_self->fetchIndexFile(); - } - return false; - }, getPoller())); + if (delay_sec == 0) { + delay_sec = delaySecond(); + } + _timer.reset(new Timer(delay_sec, [weak_self]() { + auto strong_self = weak_self.lock(); + if (strong_self) { + strong_self->fetchIndexFile(); + } + return false; + }, getPoller())); } ////////////////////////////////////////////////////////////////////////// @@ -285,7 +331,8 @@ void HlsDemuxer::start(const EventPoller::Ptr &poller, TrackListener *listener) _frame_cache.clear(); _delegate.setTrackListener(listener); - //每50毫秒执行一次 + // 每50毫秒执行一次 + // Execute every 50 milliseconds weak_ptr weak_self = shared_from_this(); _timer = std::make_shared(0.05f, [weak_self]() { auto strong_self = weak_self.lock(); @@ -306,29 +353,34 @@ void HlsDemuxer::pushTask(std::function task) { } bool HlsDemuxer::inputFrame(const Frame::Ptr &frame) { - //为了避免track准备时间过长, 因此在没准备好之前, 直接消费掉所有的帧 + // 为了避免track准备时间过长, 因此在没准备好之前, 直接消费掉所有的帧 + // In order to avoid the track preparation time is too long, so before it is ready, all frames are consumed directly if (!_delegate.isAllTrackReady()) { _delegate.inputFrame(frame); return true; } if (_frame_cache.empty()) { - //设置当前播放位置时间戳 + // 设置当前播放位置时间戳 + // Set the current playback position timestamp setPlayPosition(frame->dts()); } - //根据时间戳缓存frame + // 根据时间戳缓存frame + // Cache frame according to timestamp auto cached_frame = Frame::getCacheAbleFrame(frame); _frame_cache.emplace_back(std::make_pair(frame->dts(), [cached_frame, this]() { _delegate.inputFrame(cached_frame); })); if (getBufferMS() > 30 * 1000) { - //缓存超过30秒,强制消费至15秒(减少延时或内存占用) + // 缓存超过30秒,强制消费至15秒(减少延时或内存占用) + // The cache exceeds 30 seconds, and the consumption is forced to 15 seconds (reduce delay or memory usage) while (getBufferMS() > 15 * 1000) { _frame_cache.begin()->second(); _frame_cache.erase(_frame_cache.begin()); } - //接着播放缓存中最早的帧 + // 接着播放缓存中最早的帧 + // Then play the earliest frame in the cache setPlayPosition(_frame_cache.begin()->first); } return true; @@ -354,17 +406,21 @@ void HlsDemuxer::onTick() { auto it = _frame_cache.begin(); while (it != _frame_cache.end()) { if (it->first > getPlayPosition()) { - //这些帧还未到时间播放 + // 这些帧还未到时间播放 + // These frames are not yet time to play break; } if (getBufferMS() < 3 * 1000) { - //缓存小于3秒,那么降低定时器消费速度(让剩余的数据在3秒后消费完毕) - //目的是为了防止定时器长时间干等后,数据瞬间消费完毕 + // 缓存小于3秒,那么降低定时器消费速度(让剩余的数据在3秒后消费完毕) + // 目的是为了防止定时器长时间干等后,数据瞬间消费完毕 + // If the cache is less than 3 seconds, then reduce the speed of the timer to consume (let the remaining data be consumed after 3 seconds) + // The purpose is to prevent the timer from waiting for a long time, and the data is consumed instantly setPlayPosition(_frame_cache.begin()->first); } - //消费掉已经到期的帧 + // 消费掉已经到期的帧 + // Consume expired frames it->second(); it = _frame_cache.erase(it); } @@ -402,12 +458,14 @@ void HlsPlayerImp::onPlayResult(const SockException &ex) { void HlsPlayerImp::onShutdown(const SockException &ex) { while (_demuxer) { try { - //shared_from_this()可能抛异常 + // shared_from_this()可能抛异常 + // shared_from_this() may throw an exception std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); if (_decoder) { _decoder->flush(); } - //等待所有frame flush输出后,再触发onShutdown事件 + // 等待所有frame flush输出后,再触发onShutdown事件 + // Wait for all frame flush output, then trigger the onShutdown event static_pointer_cast(_demuxer)->pushTask([weak_self, ex]() { if (auto strong_self = weak_self.lock()) { strong_self->_demuxer = nullptr; diff --git a/src/Http/HlsPlayer.h b/src/Http/HlsPlayer.h index 422fe3f5..8f4a84b0 100644 --- a/src/Http/HlsPlayer.h +++ b/src/Http/HlsPlayer.h @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -19,12 +19,12 @@ #define MIN_TIMEOUT_MULTIPLE 2 #define MAX_TIMEOUT_MULTIPLE 5 #define MAX_TRY_FETCH_INDEX_TIMES 5 +#define MAX_TS_DOWNLOAD_FAILED_COUNT 10 namespace mediakit { class HlsDemuxer : public MediaSinkInterface , public TrackSource, public std::enable_shared_from_this { public: - HlsDemuxer() = default; ~HlsDemuxer() override { _timer = nullptr; } void start(const toolkit::EventPoller::Ptr &poller, TrackListener *listener); @@ -52,23 +52,25 @@ private: class HlsPlayer : public HttpClientImp , public PlayerBase , public HlsParser{ public: HlsPlayer(const toolkit::EventPoller::Ptr &poller); - ~HlsPlayer() override = default; /** * 开始播放 + * start play */ void play(const std::string &url) override; /** * 停止播放 + * stop play */ void teardown() override; protected: /** * 收到ts包 - * @param data ts数据负载 - * @param len ts包长度 + * Received ts package + * @param data ts数据负载 ts data payload + * @param len ts包长度 ts package length */ virtual void onPacket(const char *data, size_t len) = 0; @@ -80,7 +82,7 @@ private: bool onRedirectUrl(const std::string &url, bool temporary) override; private: - void playDelay(); + void playDelay(float delay_sec = 0); float delaySecond(); void fetchSegment(); void teardown_l(const toolkit::SockException &ex); @@ -88,7 +90,8 @@ private: private: struct UrlComp { - //url忽略?后面的参数 + // url忽略?后面的参数 + // Ignore the parameters after the url? bool operator()(const std::string& __x, const std::string& __y) const { return toolkit::split(__x,"?")[0] < toolkit::split(__y,"?")[0]; } @@ -108,13 +111,13 @@ private: HttpTSPlayer::Ptr _http_ts_player; int _timeout_multiple = MIN_TIMEOUT_MULTIPLE; int _try_fetch_index_times = 0; + int _ts_download_failed_count = 0; }; class HlsPlayerImp : public PlayerImp, private TrackListener { public: using Ptr = std::shared_ptr; HlsPlayerImp(const toolkit::EventPoller::Ptr &poller = nullptr); - ~HlsPlayerImp() override = default; private: //// HlsPlayer override//// diff --git a/src/Http/HttpBody.cpp b/src/Http/HttpBody.cpp index a2442750..cbada40f 100644 --- a/src/Http/HttpBody.cpp +++ b/src/Http/HttpBody.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -189,7 +189,6 @@ public: _data = map_addr.get() + offset; _size = size; } - ~BufferMmap() override = default; //返回数据长度 char *data() const override { return _data; } size_t size() const override { return _size; } diff --git a/src/Http/HttpBody.h b/src/Http/HttpBody.h index a23de2b1..3ba60565 100644 --- a/src/Http/HttpBody.h +++ b/src/Http/HttpBody.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -30,8 +30,6 @@ namespace mediakit { class HttpBody : public std::enable_shared_from_this{ public: using Ptr = std::shared_ptr; - HttpBody() = default; - virtual ~HttpBody() = default; /** @@ -75,7 +73,6 @@ class HttpStringBody : public HttpBody{ public: using Ptr = std::shared_ptr; HttpStringBody(std::string str); - ~HttpStringBody() override = default; int64_t remainSize() override; toolkit::Buffer::Ptr readData(size_t size) override ; @@ -92,7 +89,6 @@ class HttpBufferBody : public HttpBody{ public: using Ptr = std::shared_ptr; HttpBufferBody(toolkit::Buffer::Ptr buffer); - ~HttpBufferBody() override = default; int64_t remainSize() override; toolkit::Buffer::Ptr readData(size_t size) override; @@ -114,7 +110,6 @@ public: * @param use_mmap 是否使用mmap方式访问文件 */ HttpFileBody(const std::string &file_path, bool use_mmap = true); - ~HttpFileBody() override = default; /** * 设置读取范围 @@ -151,7 +146,6 @@ public: * @param boundary boundary字符串 */ HttpMultiFormBody(const HttpArgs &args,const std::string &filePath,const std::string &boundary = "0xKhTmLbOuNdArY"); - virtual ~HttpMultiFormBody() = default; int64_t remainSize() override ; toolkit::Buffer::Ptr readData(size_t size) override; diff --git a/src/Http/HttpChunkedSplitter.cpp b/src/Http/HttpChunkedSplitter.cpp index 2b8b3d84..248ac0ab 100644 --- a/src/Http/HttpChunkedSplitter.cpp +++ b/src/Http/HttpChunkedSplitter.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpChunkedSplitter.h b/src/Http/HttpChunkedSplitter.h index 6d8561f1..52a58053 100644 --- a/src/Http/HttpChunkedSplitter.h +++ b/src/Http/HttpChunkedSplitter.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpClient.cpp b/src/Http/HttpClient.cpp index 793e9ca1..b9927934 100644 --- a/src/Http/HttpClient.cpp +++ b/src/Http/HttpClient.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -56,10 +56,14 @@ void HttpClient::sendRequest(const string &url) { splitUrl(host, host, port); _header.emplace("Host", host_header); _header.emplace("User-Agent", kServerName); - _header.emplace("Connection", "keep-alive"); _header.emplace("Accept", "*/*"); _header.emplace("Accept-Language", "zh-CN,zh;q=0.8"); - + if (_http_persistent) { + _header.emplace("Connection", "keep-alive"); + } else { + _header.emplace("Connection", "close"); + } + _http_persistent = true; if (_body && _body->remainSize()) { _header.emplace("Content-Length", to_string(_body->remainSize())); _header.emplace("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); @@ -78,15 +82,16 @@ void HttpClient::sendRequest(const string &url) { printer.pop_back(); _header.emplace("Cookie", printer); } - if (isUsedProxy()) { - startConnect(_proxy_host, _proxy_port, _wait_header_ms / 1000.0f); - } else { - if (!alive() || host_changed) { - startConnect(host, port, _wait_header_ms / 1000.0f); + if (!alive() || host_changed || !_http_persistent) { + if (isUsedProxy()) { + _proxy_connected = false; + startConnect(_proxy_host, _proxy_port, _wait_header_ms / 1000.0f); } else { - SockException ex; - onConnect_l(ex); + startConnect(host, port, _wait_header_ms / 1000.0f); } + } else { + SockException ex; + onConnect_l(ex); } } @@ -188,6 +193,17 @@ void HttpClient::onRecv(const Buffer::Ptr &pBuf) { } void HttpClient::onError(const SockException &ex) { + if (ex.getErrCode() == Err_reset && _allow_resend_request && _http_persistent && _recved_body_size == 0 && !_header_recved) { + // 连接被重置,可能是服务器主动断开了连接, 或者服务器内核参数或防火墙的持久连接空闲时间超时或不一致. + // 如果是持久化连接,那么我们可以通过重连来解决这个问题 + // The connection was reset, possibly because the server actively disconnected the connection, + // or the persistent connection idle time of the server kernel parameters or firewall timed out or inconsistent. + // If it is a persistent connection, then we can solve this problem by reconnecting + WarnL << "http persistent connect reset, try reconnect"; + _http_persistent = false; + sendRequest(_url); + return; + } onResponseCompleted_l(ex); } @@ -219,7 +235,7 @@ ssize_t HttpClient::onRecvHeader(const char *data, size_t len) { _total_body_size = _recved_body_size; if (_recved_body_size > 0) { onResponseCompleted_l(SockException(Err_success, "success")); - }else{ + } else { onResponseCompleted_l(SockException(Err_other, "no body")); } } @@ -436,4 +452,7 @@ bool HttpClient::checkProxyConnected(const char *data, size_t len) { return _proxy_connected; } +void HttpClient::setAllowResendRequest(bool allow) { + _allow_resend_request = allow; +} } /* namespace mediakit */ diff --git a/src/Http/HttpClient.h b/src/Http/HttpClient.h index 6a00c63a..99da6ab1 100644 --- a/src/Http/HttpClient.h +++ b/src/Http/HttpClient.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -29,9 +29,6 @@ namespace mediakit { class HttpArgs : public std::map { public: - HttpArgs() = default; - ~HttpArgs() = default; - std::string make() const { std::string ret; for (auto &pr : *this) { @@ -52,9 +49,6 @@ public: using HttpHeader = StrCaseMap; using Ptr = std::shared_ptr; - HttpClient() = default; - ~HttpClient() override = default; - /** * 发送http[s]请求 * @param url 请求url @@ -146,6 +140,13 @@ public: */ void setProxyUrl(std::string proxy_url); + /** + * 当重用连接失败时, 是否允许重新发起请求 + * If the reuse connection fails, whether to allow the request to be resent + * @param allow true:允许重新发起请求 / true: allow the request to be resent + */ + void setAllowResendRequest(bool allow); + protected: /** * 收到http回复头 @@ -201,6 +202,8 @@ private: //for http response bool _complete = false; bool _header_recved = false; + bool _http_persistent = true; + bool _allow_resend_request = false; size_t _recved_body_size; ssize_t _total_body_size; Parser _parser; diff --git a/src/Http/HttpClientImp.cpp b/src/Http/HttpClientImp.cpp index 26babbb0..1858c284 100644 --- a/src/Http/HttpClientImp.cpp +++ b/src/Http/HttpClientImp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpClientImp.h b/src/Http/HttpClientImp.h index 2d32f065..d1862541 100644 --- a/src/Http/HttpClientImp.h +++ b/src/Http/HttpClientImp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -19,8 +19,6 @@ namespace mediakit { class HttpClientImp : public toolkit::TcpClientWithSSL { public: using Ptr = std::shared_ptr; - HttpClientImp() = default; - ~HttpClientImp() override = default; protected: void onConnect(const toolkit::SockException &ex) override; diff --git a/src/Http/HttpConst.cpp b/src/Http/HttpConst.cpp index 0f7409ac..7c1a896c 100644 --- a/src/Http/HttpConst.cpp +++ b/src/Http/HttpConst.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpConst.h b/src/Http/HttpConst.h index bced1a7e..a737306e 100644 --- a/src/Http/HttpConst.h +++ b/src/Http/HttpConst.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpCookie.cpp b/src/Http/HttpCookie.cpp index 07594453..5ac6bb7b 100644 --- a/src/Http/HttpCookie.cpp +++ b/src/Http/HttpCookie.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpCookie.h b/src/Http/HttpCookie.h index 60e3fbcb..171a7edc 100644 --- a/src/Http/HttpCookie.h +++ b/src/Http/HttpCookie.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -27,8 +27,6 @@ class HttpCookie { public: using Ptr = std::shared_ptr; friend class HttpCookieStorage; - HttpCookie() = default; - ~HttpCookie() = default; void setPath(const std::string &path); void setHost(const std::string &host); @@ -52,7 +50,6 @@ private: */ class HttpCookieStorage{ public: - ~HttpCookieStorage() = default; static HttpCookieStorage &Instance(); void set(const HttpCookie::Ptr &cookie); std::vector get(const std::string &host,const std::string &path); diff --git a/src/Http/HttpCookieManager.cpp b/src/Http/HttpCookieManager.cpp index e829423d..b0b7ed52 100644 --- a/src/Http/HttpCookieManager.cpp +++ b/src/Http/HttpCookieManager.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpCookieManager.h b/src/Http/HttpCookieManager.h index 53775b79..0a375e3c 100644 --- a/src/Http/HttpCookieManager.h +++ b/src/Http/HttpCookieManager.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -113,8 +113,6 @@ private: */ class RandStrGenerator { public: - RandStrGenerator() = default; - ~RandStrGenerator() = default; /** * 获取不碰撞的随机字符串 diff --git a/src/Http/HttpDownloader.cpp b/src/Http/HttpDownloader.cpp index dcb67ff7..633575cd 100644 --- a/src/Http/HttpDownloader.cpp +++ b/src/Http/HttpDownloader.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -25,7 +25,7 @@ void HttpDownloader::startDownload(const string &url, const string &file_path, b if (_file_path.empty()) { _file_path = exeDir() + "HttpDownloader/" + MD5(url).hexdigest(); } - _save_file = File::create_file(_file_path.data(), append ? "ab" : "wb"); + _save_file = File::create_file(_file_path, append ? "ab" : "wb"); if (!_save_file) { auto strErr = StrPrinter << "打开文件失败:" << file_path << endl; throw std::runtime_error(strErr); diff --git a/src/Http/HttpDownloader.h b/src/Http/HttpDownloader.h index 44a198a6..6c618aa6 100644 --- a/src/Http/HttpDownloader.h +++ b/src/Http/HttpDownloader.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,7 +20,6 @@ public: using Ptr = std::shared_ptr; using onDownloadResult = std::function; - HttpDownloader() = default; ~HttpDownloader() override; /** diff --git a/src/Http/HttpFileManager.cpp b/src/Http/HttpFileManager.cpp index 1eaa9ec1..5f6f57ad 100644 --- a/src/Http/HttpFileManager.cpp +++ b/src/Http/HttpFileManager.cpp @@ -1,26 +1,22 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ -#include -#if !defined(_WIN32) -#include -#endif //!defined(_WIN32) #include -#include "HttpFileManager.h" #include "Util/File.h" -#include "HttpConst.h" -#include "HttpSession.h" -#include "Record/HlsMediaSource.h" #include "Common/Parser.h" #include "Common/config.h" #include "Common/strCoding.h" +#include "Record/HlsMediaSource.h" +#include "HttpConst.h" +#include "HttpSession.h" +#include "HttpFileManager.h" using namespace std; using namespace toolkit; @@ -30,8 +26,8 @@ namespace mediakit { // hls的播放cookie缓存时间默认60秒, // 每次访问一次该cookie,那么将重新刷新cookie有效期 // 假如播放器在60秒内都未访问该cookie,那么将重新触发hls播放鉴权 -static int kHlsCookieSecond = 60; -static int kFindSrcIntervalSecond = 3; +static size_t kHlsCookieSecond = 60; +static size_t kFindSrcIntervalSecond = 3; static const string kCookieName = "ZL_COOKIE"; static const string kHlsSuffix = "/hls.m3u8"; static const string kHlsFMP4Suffix = "/hls.fmp4.m3u8"; @@ -158,23 +154,29 @@ bool HttpFileManager::isIPAllowed(const std::string &ip) { return false; } -static string searchIndexFile(const string &dir){ - DIR *pDir; - dirent *pDirent; - if ((pDir = opendir(dir.data())) == NULL) { - return ""; +static std::string fileName(const string &dir, const string &path) { + auto ret = path.substr(dir.size()); + if (ret.front() == '/') { + ret.erase(0, 1); } - set setFile; - while ((pDirent = readdir(pDir)) != NULL) { - static set indexSet = {"index.html", "index.htm"}; - if (indexSet.find(pDirent->d_name) != indexSet.end()) { - string ret = pDirent->d_name; - closedir(pDir); - return ret; + return ret; +} + +static string searchIndexFile(const string &dir) { + std::string ret; + static set indexSet = { "index.html", "index.htm" }; + File::scanDir(dir, [&](const string &path, bool is_dir) { + if (is_dir) { + return true; } - } - closedir(pDir); - return ""; + auto name = fileName(dir, path); + if (indexSet.find(name) == indexSet.end()) { + return true; + } + ret = std::move(name); + return false; + }); + return ret; } static bool makeFolderMenu(const string &httpPath, const string &strFullPath, string &strRet) { @@ -192,16 +194,16 @@ static bool makeFolderMenu(const string &httpPath, const string &strFullPath, st last_dir_name = split(strPathPrefix, "/").back(); } - if (!File::is_dir(strPathPrefix.data())) { + if (!File::is_dir(strPathPrefix)) { return false; } stringstream ss; ss << "\r\n" "\r\n" - "文件索引\r\n" + "File Index\r\n" "\r\n" "\r\n" - "

文件索引:"; + "

Index of "; ss << httpPath; ss << "

\r\n"; @@ -209,7 +211,7 @@ static bool makeFolderMenu(const string &httpPath, const string &strFullPath, st ss << "
  • "; - ss << "根目录"; + ss << "root"; ss << "
  • \r\n"; ss << "
  • "; - ss << "上级目录"; + ss << "../"; ss << "
  • \r\n"; } - DIR *pDir; - dirent *pDirent; - if ((pDir = opendir(strPathPrefix.data())) == NULL) { - return false; - } multimap > file_map; - while ((pDirent = readdir(pDir)) != NULL) { - if (File::is_special_dir(pDirent->d_name)) { - continue; - } - if (pDirent->d_name[0] == '.') { - continue; - } - file_map.emplace(strCoding::UrlEncode(pDirent->d_name), std::make_pair(pDirent->d_name, strPathPrefix + "/" + pDirent->d_name)); - } + File::scanDir(strPathPrefix, [&](const std::string &path, bool isDir) { + auto name = fileName(strPathPrefix, path); + file_map.emplace(strCoding::UrlEncode(name), std::make_pair(name, path)); + return true; + }); //如果是root目录,添加虚拟目录 if (httpPath == "/") { GET_CONFIG_FUNC(StrCaseMap, virtualPathMap, Http::kVirtualPath, [](const string &str) { return Parser::parseArgs(str, ";", ","); }); for (auto &pr : virtualPathMap) { - file_map.emplace(pr.first, std::make_pair(string("虚拟目录:") + pr.first, File::absolutePath("", pr.second))); + file_map.emplace(pr.first, std::make_pair(string("virtual path: ") + pr.first, File::absolutePath("", pr.second))); } } int i = 0; for (auto &pr :file_map) { auto &strAbsolutePath = pr.second.second; - bool isDir = File::is_dir(strAbsolutePath.data()); + bool isDir = File::is_dir(strAbsolutePath); ss << "
  • " << i++ << "\t"; ss << "
  • \r\n"; } - closedir(pDir); ss << "
      \r\n"; ss << "
    \r\n"; ss.str().swap(strRet); @@ -308,8 +300,6 @@ static bool emitHlsPlayed(const Parser &parser, const MediaInfo &media_info, con class SockInfoImp : public SockInfo{ public: using Ptr = std::shared_ptr; - SockInfoImp() = default; - ~SockInfoImp() override = default; string get_local_ip() override { return _local_ip; @@ -467,7 +457,7 @@ static string pathCat(const string &a, const string &b){ */ static void accessFile(Session &sender, const Parser &parser, const MediaInfo &media_info, const string &file_path, const HttpFileManager::invoker &cb) { bool is_hls = end_with(file_path, kHlsSuffix) || end_with(file_path, kHlsFMP4Suffix); - if (!is_hls && !File::fileExist(file_path.data())) { + if (!is_hls && !File::fileExist(file_path)) { //文件不存在且不是hls,那么直接返回404 sendNotFound(cb); return; @@ -584,12 +574,13 @@ static string getFilePath(const Parser &parser,const MediaInfo &media_info, Sess return Parser::parseArgs(str, ";", ","); }); - string url, path; + string url, path, virtual_app; auto it = virtualPathMap.find(media_info.app); if (it != virtualPathMap.end()) { //访问的是virtualPath path = it->second; url = parser.url().substr(1 + media_info.app.size()); + virtual_app = media_info.app + "/"; } else { //访问的是rootPath path = rootPath; @@ -608,7 +599,7 @@ static string getFilePath(const Parser &parser,const MediaInfo &media_info, Sess throw std::runtime_error("Attempting to access files outside of the http root directory"); } // 替换url,防止返回的目录索引网页被注入非法内容 - const_cast(parser).setUrl("/" + ret.substr(http_root.size())); + const_cast(parser).setUrl("/" + virtual_app + ret.substr(http_root.size())); NOTICE_EMIT(BroadcastHttpBeforeAccessArgs, Broadcast::kBroadcastHttpBeforeAccess, parser, ret, sender); return ret; } @@ -620,7 +611,7 @@ static string getFilePath(const Parser &parser,const MediaInfo &media_info, Sess * @param cb 回调对象 */ void HttpFileManager::onAccessPath(Session &sender, Parser &parser, const HttpFileManager::invoker &cb) { - auto fullUrl = string(HTTP_SCHEMA) + "://" + parser["Host"] + parser.fullUrl(); + auto fullUrl = "http://" + parser["Host"] + parser.fullUrl(); MediaInfo media_info(fullUrl); auto file_path = getFilePath(parser, media_info, sender); if (file_path.size() == 0) { @@ -628,12 +619,12 @@ void HttpFileManager::onAccessPath(Session &sender, Parser &parser, const HttpFi return; } //访问的是文件夹 - if (File::is_dir(file_path.data())) { + if (File::is_dir(file_path)) { auto indexFile = searchIndexFile(file_path); if (!indexFile.empty()) { // 发现该文件夹下有index文件 file_path = pathCat(file_path, indexFile); - if (!File::is_dir(file_path.data())) { + if (!File::is_dir(file_path)) { // 不是文件夹 parser.setUrl(pathCat(parser.url(), indexFile)); accessFile(sender, parser, media_info, file_path, cb); @@ -712,12 +703,12 @@ void HttpResponseInvokerImp::responseFile(const StrCaseMap &requestHeader, } //file是文件路径 + GET_CONFIG(string, charSet, Http::kCharSet); StrCaseMap &httpHeader = const_cast(responseHeader); auto fileBody = std::make_shared(file, use_mmap); if (fileBody->remainSize() < 0) { //打开文件失败 GET_CONFIG(string, notFound, Http::kNotFound); - GET_CONFIG(string, charSet, Http::kCharSet); auto strContentType = StrPrinter << "text/html; charset=" << charSet << endl; httpHeader["Content-Type"] = strContentType; @@ -725,6 +716,9 @@ void HttpResponseInvokerImp::responseFile(const StrCaseMap &requestHeader, return; } + // 尝试添加Content-Type + httpHeader.emplace("Content-Type", HttpConst::getHttpContentType(file.data()) + "; charset=" + charSet); + auto &strRange = const_cast(requestHeader)["Range"]; int code = 200; if (!strRange.empty()) { diff --git a/src/Http/HttpFileManager.h b/src/Http/HttpFileManager.h index a3c0c1f3..737da943 100644 --- a/src/Http/HttpFileManager.h +++ b/src/Http/HttpFileManager.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -24,8 +24,6 @@ public: typedef std::function HttpResponseInvokerLambda0; typedef std::function HttpResponseInvokerLambda1; - HttpResponseInvokerImp() = default; - ~HttpResponseInvokerImp() = default; template HttpResponseInvokerImp(const C &c):HttpResponseInvokerImp(typename toolkit::function_traits::stl_function_type(c)) {} HttpResponseInvokerImp(const HttpResponseInvokerLambda0 &lambda); diff --git a/src/Http/HttpRequestSplitter.cpp b/src/Http/HttpRequestSplitter.cpp index a7883f2f..32ab476f 100644 --- a/src/Http/HttpRequestSplitter.cpp +++ b/src/Http/HttpRequestSplitter.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -22,7 +22,7 @@ namespace mediakit { void HttpRequestSplitter::input(const char *data,size_t len) { { auto size = remainDataSize(); - if (size > kMaxCacheSize) { + if (size > _max_cache_size) { //缓存太多数据无法处理则上抛异常 reset(); throw std::out_of_range("remain data size is too huge, now cleared:" + to_string(size)); @@ -142,6 +142,16 @@ const char *HttpRequestSplitter::remainData() const { return _remain_data.data(); } +void HttpRequestSplitter::setMaxCacheSize(size_t max_cache_size) { + if (!max_cache_size) { + max_cache_size = kMaxCacheSize; + } + _max_cache_size = max_cache_size; +} + +HttpRequestSplitter::HttpRequestSplitter() { + setMaxCacheSize(0); +} } /* namespace mediakit */ diff --git a/src/Http/HttpRequestSplitter.h b/src/Http/HttpRequestSplitter.h index 5ad78bea..c4345c9f 100644 --- a/src/Http/HttpRequestSplitter.h +++ b/src/Http/HttpRequestSplitter.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -18,7 +18,7 @@ namespace mediakit { class HttpRequestSplitter { public: - HttpRequestSplitter() = default; + HttpRequestSplitter(); virtual ~HttpRequestSplitter() = default; /** @@ -44,6 +44,11 @@ public: */ const char *remainData() const; + /** + * 设置最大缓存大小 + */ + void setMaxCacheSize(size_t max_cache_size); + protected: /** * 收到请求头 @@ -80,6 +85,7 @@ protected: private: ssize_t _content_len = 0; + size_t _max_cache_size = 0; size_t _remain_data_size = 0; toolkit::BufferLikeString _remain_data; }; diff --git a/src/Http/HttpRequester.cpp b/src/Http/HttpRequester.cpp index 8bd09950..82070b2e 100644 --- a/src/Http/HttpRequester.cpp +++ b/src/Http/HttpRequester.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpRequester.h b/src/Http/HttpRequester.h index 067bb0e8..f5a5b45b 100644 --- a/src/Http/HttpRequester.h +++ b/src/Http/HttpRequester.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,9 +20,6 @@ public: using Ptr = std::shared_ptr; using HttpRequesterResult = std::function; - HttpRequester() = default; - ~HttpRequester() override = default; - void setOnResult(const HttpRequesterResult &onResult); void startRequester(const std::string &url, const HttpRequesterResult &on_result, float timeout_sec = 10); void setRetry(size_t count, size_t delay); diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index c6d390d1..38eb5473 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -24,12 +24,11 @@ using namespace toolkit; namespace mediakit { HttpSession::HttpSession(const Socket::Ptr &pSock) : Session(pSock) { - GET_CONFIG(uint32_t, keep_alive_sec, Http::kKeepAliveSecond); - pSock->setSendTimeOutSecond(keep_alive_sec); + //设置默认参数 + setMaxReqSize(0); + setTimeoutSec(0); } -HttpSession::~HttpSession() = default; - void HttpSession::onHttpRequest_HEAD() { // 暂时全部返回200 OK,因为HTTP GET存在按需生成流的操作,所以不能按照HTTP GET的流程返回 // 如果直接返回404,那么又会导致按需生成流的逻辑失效,所以HTTP HEAD在静态文件或者已存在资源时才有效 @@ -99,11 +98,10 @@ ssize_t HttpSession::onRecvHeader(const char *header, size_t len) { return _on_recv_body ? -1 : 0; } - GET_CONFIG(size_t, maxReqSize, Http::kMaxReqSize); - if (content_len > maxReqSize) { + if (content_len > _max_req_size) { //// 不定长body或超大body //// if (content_len != SIZE_MAX) { - WarnL << "Http body size is too huge: " << content_len << " > " << maxReqSize + WarnL << "Http body size is too huge: " << content_len << " > " << _max_req_size << ", please set " << Http::kMaxReqSize << " in config.ini file."; } @@ -176,11 +174,27 @@ void HttpSession::onError(const SockException &err) { } } -void HttpSession::onManager() { - GET_CONFIG(uint32_t, keepAliveSec, Http::kKeepAliveSecond); +void HttpSession::setTimeoutSec(size_t keep_alive_sec) { + if (!keep_alive_sec) { + GET_CONFIG(size_t, s_keep_alive_sec, Http::kKeepAliveSecond); + keep_alive_sec = s_keep_alive_sec; + } + _keep_alive_sec = keep_alive_sec; + getSock()->setSendTimeOutSecond(keep_alive_sec); +} - if (_ticker.elapsedTime() > keepAliveSec * 1000) { - // 1分钟超时 +void HttpSession::setMaxReqSize(size_t max_req_size) { + if (!max_req_size) { + GET_CONFIG(size_t, s_max_req_size, Http::kMaxReqSize); + max_req_size = s_max_req_size; + } + _max_req_size = max_req_size; + setMaxCacheSize(max_req_size); +} + +void HttpSession::onManager() { + if (_ticker.elapsedTime() > _keep_alive_sec * 1000) { + //http超时 shutdown(SockException(Err_timeout, "session timeout")); } } @@ -509,7 +523,6 @@ public: _body = body; _close_when_complete = close_when_complete; } - ~AsyncSenderData() = default; private: std::weak_ptr _session; diff --git a/src/Http/HttpSession.h b/src/Http/HttpSession.h index 98b43d71..33f0984f 100644 --- a/src/Http/HttpSession.h +++ b/src/Http/HttpSession.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -40,12 +40,13 @@ public: using HttpAccessPathInvoker = std::function; HttpSession(const toolkit::Socket::Ptr &pSock); - ~HttpSession() override; void onRecv(const toolkit::Buffer::Ptr &) override; void onError(const toolkit::SockException &err) override; void onManager() override; static std::string urlDecode(const std::string &str); + void setTimeoutSec(size_t second); + void setMaxReqSize(size_t max_req_size); protected: //FlvMuxer override @@ -129,6 +130,10 @@ protected: private: bool _is_live_stream = false; bool _live_over_websocket = false; + //超时时间 + size_t _keep_alive_sec = 0; + //最大http请求字节大小 + size_t _max_req_size = 0; //消耗的总流量 uint64_t _total_bytes_usage = 0; Parser _parser; diff --git a/src/Http/HttpTSPlayer.cpp b/src/Http/HttpTSPlayer.cpp index 5b2f2471..ff2f6afc 100644 --- a/src/Http/HttpTSPlayer.cpp +++ b/src/Http/HttpTSPlayer.cpp @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/HttpTSPlayer.h b/src/Http/HttpTSPlayer.h index d9dfd135..219cdcc8 100644 --- a/src/Http/HttpTSPlayer.h +++ b/src/Http/HttpTSPlayer.h @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -24,7 +24,6 @@ public: using onComplete = std::function; HttpTSPlayer(const toolkit::EventPoller::Ptr &poller = nullptr); - ~HttpTSPlayer() override = default; /** * 设置下载完毕或异常断开回调 diff --git a/src/Http/TsPlayer.cpp b/src/Http/TsPlayer.cpp index 66a7a687..339064ec 100644 --- a/src/Http/TsPlayer.cpp +++ b/src/Http/TsPlayer.cpp @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * Created by alex on 2021/4/6. - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/TsPlayer.h b/src/Http/TsPlayer.h index dfe69996..5ecd73da 100644 --- a/src/Http/TsPlayer.h +++ b/src/Http/TsPlayer.h @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * Created by alex on 2021/4/6. - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -19,7 +19,6 @@ namespace mediakit { class TsPlayer : public HttpTSPlayer, public PlayerBase { public: TsPlayer(const toolkit::EventPoller::Ptr &poller); - ~TsPlayer() override = default; /** * 开始播放 diff --git a/src/Http/TsPlayerImp.h b/src/Http/TsPlayerImp.h index 5dc32ed2..821fffb3 100644 --- a/src/Http/TsPlayerImp.h +++ b/src/Http/TsPlayerImp.h @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * Created by alex on 2021/4/6. - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -21,7 +21,6 @@ public: using Ptr = std::shared_ptr; TsPlayerImp(const toolkit::EventPoller::Ptr &poller = nullptr); - ~TsPlayerImp() override = default; private: //// TsPlayer override//// diff --git a/src/Http/TsplayerImp.cpp b/src/Http/TsplayerImp.cpp index c2e13eef..131adbd7 100644 --- a/src/Http/TsplayerImp.cpp +++ b/src/Http/TsplayerImp.cpp @@ -1,9 +1,9 @@ /* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * Created by alex on 2021/4/6. - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/WebSocketClient.h b/src/Http/WebSocketClient.h index 5850b027..9578a9d4 100644 --- a/src/Http/WebSocketClient.h +++ b/src/Http/WebSocketClient.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -37,9 +37,7 @@ public: template ClientTypeImp(ArgsType &&...args) : ClientType(std::forward(args)...) {} - ~ClientTypeImp() override = default; -protected: /** * 发送前拦截并打包为websocket协议 */ @@ -50,6 +48,7 @@ protected: return ClientType::send(std::move(buf)); } +protected: /** * 设置发送数据截取回调函数 * @param cb 截取回调函数 @@ -74,7 +73,6 @@ public: _Sec_WebSocket_Key = encodeBase64(toolkit::makeRandStr(16, false)); setPoller(delegate->getPoller()); } - ~HttpWsClient() = default; /** * 发起ws握手 diff --git a/src/Http/WebSocketSession.h b/src/Http/WebSocketSession.h index 8978330c..93bb820e 100644 --- a/src/Http/WebSocketSession.h +++ b/src/Http/WebSocketSession.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -21,7 +21,6 @@ class SendInterceptor{ public: using onBeforeSendCB =std::function; - SendInterceptor() = default; virtual ~SendInterceptor() = default; virtual void setOnBeforeSendCB(const onBeforeSendCB &cb) = 0; }; @@ -38,8 +37,6 @@ public: SessionTypeImp(const mediakit::Parser &header, const mediakit::HttpSession &parent, const toolkit::Socket::Ptr &pSock) : SessionType(pSock) {} - ~SessionTypeImp() = default; - /** * 设置发送数据截取回调函数 * @param cb 截取回调函数 @@ -82,7 +79,6 @@ template,HttpSessionType,DataType>{ public: WebSocketSession(const toolkit::Socket::Ptr &pSock) : WebSocketSessionBase,HttpSessionType,DataType>(pSock){} - virtual ~WebSocketSession() = default; }; #endif //ZLMEDIAKIT_WEBSOCKETSESSION_H diff --git a/src/Http/WebSocketSplitter.cpp b/src/Http/WebSocketSplitter.cpp index be760cca..7e17a390 100644 --- a/src/Http/WebSocketSplitter.cpp +++ b/src/Http/WebSocketSplitter.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Http/WebSocketSplitter.h b/src/Http/WebSocketSplitter.h index 72b71664..96ea2c0c 100644 --- a/src/Http/WebSocketSplitter.h +++ b/src/Http/WebSocketSplitter.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -51,6 +51,7 @@ public: //根据内存地址设置掩码随机数 _mask.assign((uint8_t*)(&ptr), (uint8_t*)(&ptr) + 4); } + virtual ~WebSocketHeader() = default; public: @@ -71,8 +72,6 @@ public: WebSocketBuffer(WebSocketHeader::Type headType, bool fin, ARGS &&...args) : toolkit::BufferString(std::forward(args)...), _fin(fin), _head_type(headType){} - ~WebSocketBuffer() override = default; - WebSocketHeader::Type headType() const { return _head_type; } bool isFinished() const { return _fin; }; @@ -84,9 +83,6 @@ private: class WebSocketSplitter : public WebSocketHeader{ public: - WebSocketSplitter() = default; - virtual ~WebSocketSplitter() = default; - /** * 输入数据以便解包webSocket数据以及处理粘包问题 * 可能触发onWebSocketDecodeHeader和onWebSocketDecodePayload回调 diff --git a/src/Player/MediaPlayer.cpp b/src/Player/MediaPlayer.cpp index 1eb5f449..c5cf5108 100644 --- a/src/Player/MediaPlayer.cpp +++ b/src/Player/MediaPlayer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -42,7 +42,9 @@ void MediaPlayer::play(const string &url) { _delegate->setOnPlayResult(_on_play_result); _delegate->setOnResume(_on_resume); _delegate->setMediaSource(_media_src); - _delegate->mINI::operator=(*this); + for (auto &pr : *this) { + (*_delegate)[pr.first] = pr.second; + } _delegate->play(url); } diff --git a/src/Player/MediaPlayer.h b/src/Player/MediaPlayer.h index a425f956..ca187019 100644 --- a/src/Player/MediaPlayer.h +++ b/src/Player/MediaPlayer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -22,7 +22,6 @@ public: using Ptr = std::shared_ptr; MediaPlayer(const toolkit::EventPoller::Ptr &poller = nullptr); - ~MediaPlayer() override = default; void play(const std::string &url) override; toolkit::EventPoller::Ptr getPoller(); diff --git a/src/Player/PlayerBase.cpp b/src/Player/PlayerBase.cpp index 3f465bd7..cda87184 100644 --- a/src/Player/PlayerBase.cpp +++ b/src/Player/PlayerBase.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Player/PlayerBase.h b/src/Player/PlayerBase.h index 73c9d3ee..b2f2f27d 100644 --- a/src/Player/PlayerBase.h +++ b/src/Player/PlayerBase.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -32,7 +32,6 @@ public: static Ptr createPlayer(const toolkit::EventPoller::Ptr &poller, const std::string &strUrl); PlayerBase(); - ~PlayerBase() override = default; /** * 开始播放 @@ -128,7 +127,6 @@ public: template PlayerImp(ArgsType &&...args) : Parent(std::forward(args)...) {} - ~PlayerImp() override = default; void play(const std::string &url) override { return _delegate ? _delegate->play(url) : Parent::play(url); diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 73e46b71..0f31e33b 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -1,16 +1,15 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "PlayerProxy.h" #include "Common/config.h" -#include "Extension/AAC.h" #include "Rtmp/RtmpMediaSource.h" #include "Rtmp/RtmpPlayer.h" #include "Rtsp/RtspMediaSource.h" @@ -97,7 +96,16 @@ void PlayerProxy::setTranslationInfo() } } +static int getMaxTrackSize(const std::string &url) { + if (url.find(".m3u8") != std::string::npos || url.find(".ts") != std::string::npos) { + // hls和ts协议才开放多track支持 + return 16; + } + return 2; +} + void PlayerProxy::play(const string &strUrlTmp) { + _option.max_track = getMaxTrackSize(strUrlTmp); weak_ptr weakSelf = shared_from_this(); std::shared_ptr piFailedCnt(new int(0)); // 连续播放失败次数 setOnPlayResult([weakSelf, strUrlTmp, piFailedCnt](const SockException &err) { @@ -191,8 +199,11 @@ void PlayerProxy::setDirectProxy() { mediaSource = std::make_shared(_tuple); } } else if (dynamic_pointer_cast(_delegate)) { - // rtmp拉流,rtmp强制直接代理 - mediaSource = std::make_shared(_tuple); + // rtmp拉流 + GET_CONFIG(bool, directProxy, Rtmp::kDirectProxy); + if (directProxy) { + mediaSource = std::make_shared(_tuple); + } } if (mediaSource) { setMediaSource(mediaSource); diff --git a/src/Player/PlayerProxy.h b/src/Player/PlayerProxy.h index a0d1cf32..c3c5b5bc 100644 --- a/src/Player/PlayerProxy.h +++ b/src/Player/PlayerProxy.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Pusher/MediaPusher.cpp b/src/Pusher/MediaPusher.cpp index f0ea401b..494f0eee 100644 --- a/src/Pusher/MediaPusher.cpp +++ b/src/Pusher/MediaPusher.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -31,8 +31,6 @@ MediaPusher::MediaPusher(const string &schema, MediaPusher(MediaSource::find(schema, vhost, app, stream), poller){ } -MediaPusher::~MediaPusher() = default; - static void setOnCreateSocket_l(const std::shared_ptr &delegate, const Socket::onCreateSocket &cb){ auto helper = dynamic_pointer_cast(delegate); if (helper) { diff --git a/src/Pusher/MediaPusher.h b/src/Pusher/MediaPusher.h index 52bd4ec3..899f7cf2 100644 --- a/src/Pusher/MediaPusher.h +++ b/src/Pusher/MediaPusher.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -30,8 +30,6 @@ public: MediaPusher(const MediaSource::Ptr &src, const toolkit::EventPoller::Ptr &poller = nullptr); - virtual ~MediaPusher(); - void publish(const std::string &url) override; toolkit::EventPoller::Ptr getPoller(); void setOnCreateSocket(toolkit::Socket::onCreateSocket cb); diff --git a/src/Pusher/PusherBase.cpp b/src/Pusher/PusherBase.cpp index eddbf7b8..ac90d841 100644 --- a/src/Pusher/PusherBase.cpp +++ b/src/Pusher/PusherBase.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Pusher/PusherBase.h b/src/Pusher/PusherBase.h index 8d97588b..fa5b879b 100644 --- a/src/Pusher/PusherBase.h +++ b/src/Pusher/PusherBase.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -66,7 +66,6 @@ public: template PusherImp(ArgsType &&...args) : Parent(std::forward(args)...) {} - ~PusherImp() override = default; /** * 开始推流 diff --git a/src/Pusher/PusherProxy.cpp b/src/Pusher/PusherProxy.cpp index ffe1a500..de22f302 100644 --- a/src/Pusher/PusherProxy.cpp +++ b/src/Pusher/PusherProxy.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Pusher/PusherProxy.h b/src/Pusher/PusherProxy.h index e0146514..8a61488c 100644 --- a/src/Pusher/PusherProxy.h +++ b/src/Pusher/PusherProxy.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Record/HlsMaker.cpp b/src/Record/HlsMaker.cpp index 31f705b8..2b074e1b 100644 --- a/src/Record/HlsMaker.cpp +++ b/src/Record/HlsMaker.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -111,11 +111,11 @@ void HlsMaker::delOldSegment() { } void HlsMaker::addNewSegment(uint64_t stamp) { - if (!_last_file_name.empty() && stamp - _last_seg_timestamp < _seg_duration * 1000) { - //存在上个切片,并且未到分片时间 + GET_CONFIG(bool, fastRegister, Hls::kFastRegister); + if (_file_index > fastRegister && stamp - _last_seg_timestamp < _seg_duration * 1000) { + //确保序号为0的切片立即open,如果开启快速注册功能,序号为1的切片也应该遇到关键帧立即生成;否则需要等切片时长够长 return; } - //关闭并保存上一个切片,如果_seg_number==0,那么是点播。 flushLastSegment(false); //新增切片 diff --git a/src/Record/HlsMaker.h b/src/Record/HlsMaker.h index 185a19d1..c06117e7 100644 --- a/src/Record/HlsMaker.h +++ b/src/Record/HlsMaker.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Record/HlsMakerImp.cpp b/src/Record/HlsMakerImp.cpp index 2ba99f76..7fc2b000 100644 --- a/src/Record/HlsMakerImp.cpp +++ b/src/Record/HlsMakerImp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -45,6 +45,13 @@ void HlsMakerImp::clearCache() { clearCache(true, false); } +static void clearHls(const std::list &files) { + for (auto &file : files) { + File::delete_file(file); + } + File::deleteEmptyDir(File::parentDir(files.back())); +} + void HlsMakerImp::clearCache(bool immediately, bool eof) { // 录制完了 flushLastSegment(eof); @@ -52,21 +59,31 @@ void HlsMakerImp::clearCache(bool immediately, bool eof) { return; } + { + std::list lst; + lst.emplace_back(_path_hls); + if (!_path_init.empty()) { + lst.emplace_back(_path_init); + } + for (auto &pr : _segment_file_paths) { + lst.emplace_back(std::move(pr.second)); + } + + // hls直播才删除文件 + GET_CONFIG(uint32_t, delay, Hls::kDeleteDelaySec); + if (!delay || immediately) { + clearHls(lst); + } else { + _poller->doDelayTask(delay * 1000, [lst]() { + clearHls(lst); + return 0; + }); + } + } + clear(); _file = nullptr; _segment_file_paths.clear(); - - // hls直播才删除文件 - GET_CONFIG(uint32_t, delay, Hls::kDeleteDelaySec); - if (!delay || immediately) { - File::delete_file(_path_prefix.data()); - } else { - auto path_prefix = _path_prefix; - _poller->doDelayTask(delay * 1000, [path_prefix]() { - File::delete_file(path_prefix.data()); - return 0; - }); - } } string HlsMakerImp::onOpenSegment(uint64_t index) { @@ -103,16 +120,17 @@ void HlsMakerImp::onDelSegment(uint64_t index) { if (it == _segment_file_paths.end()) { return; } - File::delete_file(it->second.data()); + File::delete_file(it->second.data(), true); _segment_file_paths.erase(it); } void HlsMakerImp::onWriteInitSegment(const char *data, size_t len) { string init_seg_path = _path_prefix + "/init.mp4"; - _file = makeFile(init_seg_path, true); + _file = makeFile(init_seg_path); if (_file) { fwrite(data, len, 1, _file.get()); + _path_init = std::move(init_seg_path); _file = nullptr; } else { WarnL << "Create file failed," << init_seg_path << " " << get_uv_errmsg(); diff --git a/src/Record/HlsMakerImp.h b/src/Record/HlsMakerImp.h index 07bef1d6..7d268a53 100644 --- a/src/Record/HlsMakerImp.h +++ b/src/Record/HlsMakerImp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -60,6 +60,7 @@ private: int _buf_size; std::string _params; std::string _path_hls; + std::string _path_init; std::string _path_prefix; RecordInfo _info; std::shared_ptr _file; diff --git a/src/Record/HlsMediaSource.cpp b/src/Record/HlsMediaSource.cpp index f3adb775..382e2779 100644 --- a/src/Record/HlsMediaSource.cpp +++ b/src/Record/HlsMediaSource.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Record/HlsMediaSource.h b/src/Record/HlsMediaSource.h index 1e0ecd14..f9c4c56d 100644 --- a/src/Record/HlsMediaSource.h +++ b/src/Record/HlsMediaSource.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -26,7 +26,6 @@ public: using Ptr = std::shared_ptr; HlsMediaSource(const std::string &schema, const MediaTuple &tuple) : MediaSource(schema, tuple) {} - ~HlsMediaSource() override = default; /** * 获取媒体源的环形缓冲 diff --git a/src/Record/HlsRecorder.h b/src/Record/HlsRecorder.h index aa1a4960..f6e84bfb 100644 --- a/src/Record/HlsRecorder.h +++ b/src/Record/HlsRecorder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -33,8 +33,6 @@ public: _hls->clearCache(); } - ~HlsRecorderBase() override = default; - void setMediaSource(const MediaTuple& tuple) { _hls->setMediaSource(tuple.vhost, tuple.app, tuple.stream); } diff --git a/src/Record/MP4.cpp b/src/Record/MP4.cpp index 10f1b0ee..793c7794 100644 --- a/src/Record/MP4.cpp +++ b/src/Record/MP4.cpp @@ -1,14 +1,14 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ -#if defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) #include "MP4.h" #include "Util/File.h" @@ -177,4 +177,4 @@ int MP4FileMemory::onWrite(const void *data, size_t bytes){ } }//namespace mediakit -#endif // defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#endif // defined(ENABLE_MP4) diff --git a/src/Record/MP4.h b/src/Record/MP4.h index 63e7af9c..4b150170 100644 --- a/src/Record/MP4.h +++ b/src/Record/MP4.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,7 +11,7 @@ #ifndef ZLMEDIAKIT_MP4_H #define ZLMEDIAKIT_MP4_H -#if defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) #include #include @@ -33,7 +33,6 @@ public: using Writer = std::shared_ptr; using Reader = std::shared_ptr; - MP4FileIO() = default; virtual ~MP4FileIO() = default; /** @@ -83,8 +82,6 @@ public: class MP4FileDisk : public MP4FileIO { public: using Ptr = std::shared_ptr; - MP4FileDisk() = default; - ~MP4FileDisk() override = default; /** * 打开磁盘文件 @@ -111,8 +108,6 @@ private: class MP4FileMemory : public MP4FileIO{ public: using Ptr = std::shared_ptr; - MP4FileMemory() = default; - ~MP4FileMemory() override = default; /** * 获取文件大小 @@ -136,5 +131,5 @@ private: }; }//namespace mediakit -#endif //defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#endif //defined(ENABLE_MP4) #endif //ZLMEDIAKIT_MP4_H diff --git a/src/Record/MP4Demuxer.cpp b/src/Record/MP4Demuxer.cpp index 87936137..4d6800d2 100644 --- a/src/Record/MP4Demuxer.cpp +++ b/src/Record/MP4Demuxer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,20 +11,13 @@ #ifdef ENABLE_MP4 #include "MP4Demuxer.h" #include "Util/logger.h" -#include "Extension/H265.h" -#include "Extension/H264.h" -#include "Extension/AAC.h" -#include "Extension/G711.h" -#include "Extension/Opus.h" -#include "Extension/JPEG.h" +#include "Extension/Factory.h" using namespace std; using namespace toolkit; namespace mediakit { -MP4Demuxer::MP4Demuxer() = default; - MP4Demuxer::~MP4Demuxer() { closeMP4(); } @@ -63,103 +56,27 @@ int MP4Demuxer::getAllTracks() { return mov_reader_getinfo(_mov_reader.get(),&s_on_track,this); } -#define SWITCH_CASE(obj_id) case obj_id : return #obj_id -static const char *getObjectName(int obj_id) { - switch (obj_id) { - SWITCH_CASE(MOV_OBJECT_TEXT); - SWITCH_CASE(MOV_OBJECT_MP4V); - SWITCH_CASE(MOV_OBJECT_H264); - SWITCH_CASE(MOV_OBJECT_HEVC); - SWITCH_CASE(MOV_OBJECT_AAC); - SWITCH_CASE(MOV_OBJECT_MP2V); - SWITCH_CASE(MOV_OBJECT_AAC_MAIN); - SWITCH_CASE(MOV_OBJECT_AAC_LOW); - SWITCH_CASE(MOV_OBJECT_AAC_SSR); - SWITCH_CASE(MOV_OBJECT_MP3); - SWITCH_CASE(MOV_OBJECT_MP1V); - SWITCH_CASE(MOV_OBJECT_MP1A); - SWITCH_CASE(MOV_OBJECT_JPEG); - SWITCH_CASE(MOV_OBJECT_PNG); - SWITCH_CASE(MOV_OBJECT_JPEG2000); - SWITCH_CASE(MOV_OBJECT_G719); - SWITCH_CASE(MOV_OBJECT_OPUS); - SWITCH_CASE(MOV_OBJECT_G711a); - SWITCH_CASE(MOV_OBJECT_G711u); - SWITCH_CASE(MOV_OBJECT_AV1); - default: - return "unknown mp4 object"; - } -} - - void MP4Demuxer::onVideoTrack(uint32_t track, uint8_t object, int width, int height, const void *extra, size_t bytes) { - switch (object) { - case MOV_OBJECT_H264: { - auto video = std::make_shared(); - _track_to_codec.emplace(track,video); - - struct mpeg4_avc_t avc; - memset(&avc, 0, sizeof(avc)); - if (mpeg4_avc_decoder_configuration_record_load((uint8_t *) extra, bytes, &avc) > 0) { - uint8_t config[1024 * 10] = {0}; - int size = mpeg4_avc_to_nalu(&avc, config, sizeof(config)); - if (size > 0) { - video->inputFrame(std::make_shared((char *)config, size, 0, 0,4)); - } - } - break; - } - - case MOV_OBJECT_HEVC: { - auto video = std::make_shared(); - _track_to_codec.emplace(track,video); - - struct mpeg4_hevc_t hevc; - memset(&hevc, 0, sizeof(hevc)); - if (mpeg4_hevc_decoder_configuration_record_load((uint8_t *) extra, bytes, &hevc) > 0) { - uint8_t config[1024 * 10] = {0}; - int size = mpeg4_hevc_to_nalu(&hevc, config, sizeof(config)); - if (size > 0) { - video->inputFrame(std::make_shared((char *) config, size, 0, 0,4)); - } - } - break; - } - - case MOV_OBJECT_JPEG: { - auto video = std::make_shared(); - _track_to_codec.emplace(track,video); - break; - } - - default: WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object); break; + auto video = Factory::getTrackByCodecId(getCodecByMovId(object)); + if (!video) { + return; + } + video->setIndex(track); + _tracks.emplace(track, video); + if (extra && bytes) { + video->setExtraData((uint8_t *)extra, bytes); } } -void MP4Demuxer::onAudioTrack(uint32_t track_id, uint8_t object, int channel_count, int bit_per_sample, int sample_rate, const void *extra, size_t bytes) { - switch(object){ - case MOV_OBJECT_AAC:{ - auto audio = std::make_shared(bytes > 0 ? string((char *)extra,bytes) : ""); - _track_to_codec.emplace(track_id, audio); - break; - } - - case MOV_OBJECT_G711a: - case MOV_OBJECT_G711u:{ - auto audio = std::make_shared(object == MOV_OBJECT_G711a ? CodecG711A : CodecG711U, sample_rate, channel_count, bit_per_sample / channel_count ); - _track_to_codec.emplace(track_id, audio); - break; - } - - case MOV_OBJECT_OPUS: { - auto audio = std::make_shared(); - _track_to_codec.emplace(track_id, audio); - break; - } - - default: - WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object); - break; +void MP4Demuxer::onAudioTrack(uint32_t track, uint8_t object, int channel_count, int bit_per_sample, int sample_rate, const void *extra, size_t bytes) { + auto audio = Factory::getTrackByCodecId(getCodecByMovId(object), sample_rate, channel_count, bit_per_sample / channel_count); + if (!audio) { + return; + } + audio->setIndex(track); + _tracks.emplace(track, audio); + if (extra && bytes) { + audio->setExtraData((uint8_t *)extra, bytes); } } @@ -180,8 +97,6 @@ struct Context { BufferRaw::Ptr buffer; }; -#define DATA_OFFSET ADTS_HEADER_LEN - Frame::Ptr MP4Demuxer::readFrame(bool &keyFrame, bool &eof) { keyFrame = false; eof = false; @@ -194,9 +109,9 @@ Frame::Ptr MP4Demuxer::readFrame(bool &keyFrame, bool &eof) { ctx->track_id = track_id; ctx->buffer = ctx->thiz->_buffer_pool.obtain2(); - ctx->buffer->setCapacity(bytes + DATA_OFFSET + 1); - ctx->buffer->setSize(bytes + DATA_OFFSET); - return ctx->buffer->data() + DATA_OFFSET; + ctx->buffer->setCapacity(bytes + 1); + ctx->buffer->setSize(bytes); + return ctx->buffer->data(); }; Context ctx(this); @@ -221,18 +136,18 @@ Frame::Ptr MP4Demuxer::readFrame(bool &keyFrame, bool &eof) { } Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int64_t pts, int64_t dts) { - auto it = _track_to_codec.find(track_id); - if (it == _track_to_codec.end()) { + auto it = _tracks.find(track_id); + if (it == _tracks.end()) { return nullptr; } - auto bytes = buf->size() - DATA_OFFSET; - auto data = buf->data() + DATA_OFFSET; - auto codec = it->second->getCodecId(); Frame::Ptr ret; + auto codec = it->second->getCodecId(); switch (codec) { - case CodecH264 : - case CodecH265 : { - uint32_t offset = 0; + case CodecH264: + case CodecH265: { + auto bytes = buf->size(); + auto data = buf->data(); + auto offset = 0u; while (offset < bytes) { uint32_t frame_len; memcpy(&frame_len, data + offset, 4); @@ -243,47 +158,26 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6 memcpy(data + offset, "\x00\x00\x00\x01", 4); offset += (frame_len + 4); } - if (codec == CodecH264) { - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 4, DATA_OFFSET); - break; - } - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 4, DATA_OFFSET); + ret = Factory::getFrameFromBuffer(codec, std::move(buf), dts, pts); break; } - case CodecJPEG: { - ret = std::make_shared(buf, (uint64_t)dts, 0, DATA_OFFSET); + default: { + ret = Factory::getFrameFromBuffer(codec, std::move(buf), dts, pts); break; } - - case CodecAAC: { - AACTrack::Ptr track = dynamic_pointer_cast(it->second); - assert(track); - //加上adts头 - dumpAacConfig(track->getConfig(), buf->size() - DATA_OFFSET, (uint8_t *) buf->data() + (DATA_OFFSET - ADTS_HEADER_LEN), ADTS_HEADER_LEN); - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, ADTS_HEADER_LEN, DATA_OFFSET - ADTS_HEADER_LEN, codec); - break; - } - - case CodecOpus: - case CodecG711A: - case CodecG711U: { - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 0, DATA_OFFSET, codec); - break; - } - - default: return nullptr; } if (ret) { + ret->setIndex(track_id); it->second->inputFrame(ret); } return ret; } -vector MP4Demuxer::getTracks(bool trackReady) const { +vector MP4Demuxer::getTracks(bool ready) const { vector ret; - for (auto &pr : _track_to_codec) { - if(trackReady && !pr.second->ready()){ + for (auto &pr : _tracks) { + if (ready && !pr.second->ready()) { continue; } ret.push_back(pr.second); diff --git a/src/Record/MP4Demuxer.h b/src/Record/MP4Demuxer.h index 220f143a..889f91fc 100644 --- a/src/Record/MP4Demuxer.h +++ b/src/Record/MP4Demuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,10 +20,6 @@ class MP4Demuxer : public TrackSource { public: using Ptr = std::shared_ptr; - /** - * 创建mp4解复用器 - */ - MP4Demuxer(); ~MP4Demuxer() override; /** @@ -75,7 +71,7 @@ private: MP4FileDisk::Ptr _mp4_file; MP4FileDisk::Reader _mov_reader; uint64_t _duration_ms = 0; - std::map _track_to_codec; + std::unordered_map _tracks; toolkit::ResourcePool _buffer_pool; }; diff --git a/src/Record/MP4Muxer.cpp b/src/Record/MP4Muxer.cpp index 5458a31d..37c6cfd7 100644 --- a/src/Record/MP4Muxer.cpp +++ b/src/Record/MP4Muxer.cpp @@ -1,21 +1,16 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ -#if defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) #include "MP4Muxer.h" -#include "Extension/AAC.h" -#include "Extension/G711.h" -#include "Extension/H264.h" -#include "Extension/H265.h" -#include "Extension/JPEG.h" #include "Common/config.h" using namespace std; @@ -65,7 +60,7 @@ bool MP4MuxerInterface::haveVideo() const { uint64_t MP4MuxerInterface::getDuration() const { uint64_t ret = 0; - for (auto &pr : _codec_to_trackid) { + for (auto &pr : _tracks) { if (pr.second.stamp.getRelativeStamp() > (int64_t)ret) { ret = pr.second.stamp.getRelativeStamp(); } @@ -77,272 +72,109 @@ void MP4MuxerInterface::resetTracks() { _started = false; _have_video = false; _mov_writter = nullptr; - _frame_merger.clear(); - _codec_to_trackid.clear(); + _tracks.clear(); } void MP4MuxerInterface::flush() { - _frame_merger.flush(); + for (auto &pr : _tracks) { + pr.second.merger.flush(); + } } bool MP4MuxerInterface::inputFrame(const Frame::Ptr &frame) { - auto it = _codec_to_trackid.find(frame->getCodecId()); - if (it == _codec_to_trackid.end()) { - //该Track不存在或初始化失败 + auto it = _tracks.find(frame->getIndex()); + if (it == _tracks.end()) { + // 该Track不存在或初始化失败 return false; } if (!_started) { - //该逻辑确保含有视频时,第一帧为关键帧 + // 该逻辑确保含有视频时,第一帧为关键帧 if (_have_video && !frame->keyFrame()) { - //含有视频,但是不是关键帧,那么前面的帧丢弃 + // 含有视频,但是不是关键帧,那么前面的帧丢弃 return false; } - //开始写文件 + // 开始写文件 _started = true; } - //mp4文件时间戳需要从0开始 - auto &track_info = it->second; + // mp4文件时间戳需要从0开始 + auto &track = it->second; switch (frame->getCodecId()) { case CodecH264: case CodecH265: { - //这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理, - _frame_merger.inputFrame(frame, [this, &track_info](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) { + // 这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理, + track.merger.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) { int64_t dts_out, pts_out; - track_info.stamp.revise(dts, pts, dts_out, pts_out); - mp4_writer_write(_mov_writter.get(), - track_info.track_id, - buffer->data(), - buffer->size(), - pts_out, - dts_out, - have_idr ? MOV_AV_FLAG_KEYFREAME : 0); + track.stamp.revise(dts, pts, dts_out, pts_out); + mp4_writer_write(_mov_writter.get(), track.track_id, buffer->data(), buffer->size(), pts_out, dts_out, have_idr ? MOV_AV_FLAG_KEYFREAME : 0); }); break; } - case CodecJPEG:{ - int64_t dts_out, pts_out; - track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out); - mp4_writer_write(_mov_writter.get(), - track_info.track_id, - frame->data(), - frame->size(), - pts_out, - dts_out, - frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0); - break; - } default: { int64_t dts_out, pts_out; - track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out); - mp4_writer_write(_mov_writter.get(), - track_info.track_id, - frame->data() + frame->prefixSize(), - frame->size() - frame->prefixSize(), - pts_out, - dts_out, - frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0); + track.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out); + mp4_writer_write(_mov_writter.get(), track.track_id, frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize(), pts_out, dts_out, frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0); break; } } return true; } -static uint8_t getObject(CodecId codecId) { - switch (codecId){ - case CodecG711A : return MOV_OBJECT_G711a; - case CodecG711U : return MOV_OBJECT_G711u; - case CodecOpus : return MOV_OBJECT_OPUS; - case CodecAAC : return MOV_OBJECT_AAC; - case CodecH264 : return MOV_OBJECT_H264; - case CodecH265 : return MOV_OBJECT_HEVC; - case CodecJPEG : return MOV_OBJECT_JPEG; - default : return 0; - } -} - void MP4MuxerInterface::stampSync() { - if (_codec_to_trackid.size() < 2) { - return; - } - - Stamp *audio = nullptr, *video = nullptr; - for(auto &pr : _codec_to_trackid){ - switch (getTrackType((CodecId) pr.first)){ - case TrackAudio : audio = &pr.second.stamp; break; - case TrackVideo : video = &pr.second.stamp; break; - default : break; + Stamp *first = nullptr; + for (auto &pr : _tracks) { + if (!first) { + first = &pr.second.stamp; + } else { + pr.second.stamp.syncTo(*first); } } - - if (audio && video) { - //音频时间戳同步于视频,因为音频时间戳被修改后不影响播放 - audio->syncTo(*video); - } } bool MP4MuxerInterface::addTrack(const Track::Ptr &track) { if (!_mov_writter) { _mov_writter = createWriter(); } - auto mp4_object = getObject(track->getCodecId()); - if (!mp4_object) { - WarnL << "MP4录制不支持该编码格式:" << track->getCodecName(); + auto mp4_object = getMovIdByCodec(track->getCodecId()); + if (mp4_object == MOV_OBJECT_NONE) { + WarnL << "Unsupported codec: " << track->getCodecName(); return false; } if (!track->ready()) { - WarnL << "Track[" << track->getCodecName() << "]未就绪"; + WarnL << "Track " << track->getCodecName() << " unready"; return false; } track->update(); - switch (track->getCodecId()) { - case CodecG711A: - case CodecG711U: - case CodecOpus: { - auto audio_track = dynamic_pointer_cast(track); - if (!audio_track) { - WarnL << "不是音频Track:" << track->getCodecName(); - return false; - } - auto track_id = mp4_writer_add_audio(_mov_writter.get(), - mp4_object, - audio_track->getAudioChannel(), - audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), - audio_track->getAudioSampleRate(), - nullptr, 0); - if (track_id < 0) { - WarnL << "添加Track[" << track->getCodecName() << "]失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - break; + auto extra = track->getExtraData(); + auto extra_data = extra ? extra->data() : nullptr; + auto extra_size = extra ? extra->size() : 0; + if (track->getTrackType() == TrackVideo) { + auto video_track = dynamic_pointer_cast(track); + CHECK(video_track); + auto track_id = mp4_writer_add_video(_mov_writter.get(), mp4_object, video_track->getVideoWidth(), video_track->getVideoHeight(), extra_data, extra_size); + if (track_id < 0) { + WarnL << "mp4_writer_add_video failed: " << video_track->getCodecName(); + return false; } - - case CodecAAC: { - auto audio_track = dynamic_pointer_cast(track); - if (!audio_track) { - WarnL << "不是AAC Track"; - return false; - } - - auto track_id = mp4_writer_add_audio(_mov_writter.get(), - mp4_object, - audio_track->getAudioChannel(), - audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), - audio_track->getAudioSampleRate(), - audio_track->getConfig().data(), - audio_track->getConfig().size()); - if (track_id < 0) { - WarnL << "添加AAC Track失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - break; + _tracks[track->getIndex()].track_id = track_id; + _have_video = true; + } else if (track->getTrackType() == TrackAudio) { + auto audio_track = dynamic_pointer_cast(track); + CHECK(audio_track); + auto track_id = mp4_writer_add_audio(_mov_writter.get(), mp4_object, audio_track->getAudioChannel(), audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), audio_track->getAudioSampleRate(), extra_data, extra_size); + if (track_id < 0) { + WarnL << "mp4_writer_add_audio failed: " << audio_track->getCodecName(); + return false; } - - case CodecH264: { - auto h264_track = dynamic_pointer_cast(track); - if (!h264_track) { - WarnL << "不是H264 Track"; - return false; - } - - struct mpeg4_avc_t avc; - memset(&avc, 0, sizeof(avc)); - string sps_pps = string("\x00\x00\x00\x01", 4) + h264_track->getSps() + - string("\x00\x00\x00\x01", 4) + h264_track->getPps(); - h264_annexbtomp4(&avc, sps_pps.data(), (int) sps_pps.size(), NULL, 0, NULL, NULL); - - uint8_t extra_data[1024]; - int extra_data_size = mpeg4_avc_decoder_configuration_record_save(&avc, extra_data, sizeof(extra_data)); - if (extra_data_size == -1) { - WarnL << "生成H264 extra_data 失败"; - return false; - } - - auto track_id = mp4_writer_add_video(_mov_writter.get(), - mp4_object, - h264_track->getVideoWidth(), - h264_track->getVideoHeight(), - extra_data, - extra_data_size); - - if (track_id < 0) { - WarnL << "添加H264 Track失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - _have_video = true; - break; - } - - case CodecH265: { - auto h265_track = dynamic_pointer_cast(track); - if (!h265_track) { - WarnL << "不是H265 Track"; - return false; - } - - struct mpeg4_hevc_t hevc; - memset(&hevc, 0, sizeof(hevc)); - string vps_sps_pps = string("\x00\x00\x00\x01", 4) + h265_track->getVps() + - string("\x00\x00\x00\x01", 4) + h265_track->getSps() + - string("\x00\x00\x00\x01", 4) + h265_track->getPps(); - h265_annexbtomp4(&hevc, vps_sps_pps.data(), (int) vps_sps_pps.size(), NULL, 0, NULL, NULL); - - uint8_t extra_data[1024]; - int extra_data_size = mpeg4_hevc_decoder_configuration_record_save(&hevc, extra_data, sizeof(extra_data)); - if (extra_data_size == -1) { - WarnL << "生成H265 extra_data 失败"; - return false; - } - - auto track_id = mp4_writer_add_video(_mov_writter.get(), - mp4_object, - h265_track->getVideoWidth(), - h265_track->getVideoHeight(), - extra_data, - extra_data_size); - if (track_id < 0) { - WarnL << "添加H265 Track失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - _have_video = true; - break; - } - - case CodecJPEG: { - auto jpeg_track = dynamic_pointer_cast(track); - if (!jpeg_track) { - WarnL << "不是JPEG Track"; - return false; - } - - auto track_id = mp4_writer_add_video(_mov_writter.get(), - mp4_object, - jpeg_track->getVideoWidth(), - jpeg_track->getVideoHeight(), - nullptr, - 0); - if (track_id < 0) { - WarnL << "添加JPEG Track失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - _have_video = true; - break; - } - - default: WarnL << "MP4录制不支持该编码格式:" << track->getCodecName(); return false; + _tracks[track->getIndex()].track_id = track_id; } - //尝试音视频同步 + // 尝试音视频同步 stampSync(); return true; } @@ -374,7 +206,7 @@ void MP4MuxerMemory::resetTracks() { bool MP4MuxerMemory::inputFrame(const Frame::Ptr &frame) { if (_init_segment.empty()) { - //尚未生成init segment + // 尚未生成init segment return false; } @@ -397,5 +229,5 @@ bool MP4MuxerMemory::inputFrame(const Frame::Ptr &frame) { return MP4MuxerInterface::inputFrame(frame); } -}//namespace mediakit -#endif //defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +} // namespace mediakit +#endif // defined(ENABLE_MP4) diff --git a/src/Record/MP4Muxer.h b/src/Record/MP4Muxer.h index 3b48ad7c..4f764c3f 100644 --- a/src/Record/MP4Muxer.h +++ b/src/Record/MP4Muxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,7 +11,7 @@ #ifndef ZLMEDIAKIT_MP4MUXER_H #define ZLMEDIAKIT_MP4MUXER_H -#if defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) #include "Common/MediaSink.h" #include "Common/Stamp.h" @@ -21,8 +21,6 @@ namespace mediakit { class MP4MuxerInterface : public MediaSinkInterface { public: - MP4MuxerInterface() = default; - ~MP4MuxerInterface() override = default; /** * 添加已经ready状态的track @@ -74,21 +72,24 @@ private: bool _started = false; bool _have_video = false; MP4FileIO::Writer _mov_writter; - struct track_info { + + class FrameMergerImp : public FrameMerger { + public: + FrameMergerImp() : FrameMerger(FrameMerger::mp4_nal_size) {} + }; + + struct MP4Track { int track_id = -1; Stamp stamp; + FrameMergerImp merger; }; - std::unordered_map _codec_to_trackid; - FrameMerger _frame_merger { FrameMerger::mp4_nal_size }; + std::unordered_map _tracks; }; class MP4Muxer : public MP4MuxerInterface{ public: using Ptr = std::shared_ptr; - - MP4Muxer() = default; ~MP4Muxer() override; - /** * 重置所有track */ @@ -116,7 +117,6 @@ private: class MP4MuxerMemory : public MP4MuxerInterface{ public: MP4MuxerMemory(); - ~MP4MuxerMemory() override = default; /** * 重置所有track @@ -162,9 +162,6 @@ namespace mediakit { class MP4MuxerMemory : public MediaSinkInterface { public: - MP4MuxerMemory() = default; - ~MP4MuxerMemory() override = default; - bool addTrack(const Track::Ptr & track) override { return false; } bool inputFrame(const Frame::Ptr &frame) override { return false; } const std::string &getInitSegment() { static std::string kNull; return kNull; }; @@ -181,5 +178,5 @@ protected: } // namespace mediakit -#endif //defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#endif //defined(ENABLE_MP4) #endif //ZLMEDIAKIT_MP4MUXER_H diff --git a/src/Record/MP4Reader.cpp b/src/Record/MP4Reader.cpp index d1f408dd..e70f9fe8 100644 --- a/src/Record/MP4Reader.cpp +++ b/src/Record/MP4Reader.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,24 +20,26 @@ using namespace toolkit; namespace mediakit { -MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path) { +MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path, + toolkit::EventPoller::Ptr poller) { ProtocolOption option; // 读取mp4文件并流化时,不重复生成mp4/hls文件 option.enable_mp4 = false; option.enable_hls = false; option.enable_hls_fmp4 = false; - - setup(vhost, app, stream_id, file_path, option); + // mp4支持多track + option.max_track = 16; + setup(vhost, app, stream_id, file_path, option, std::move(poller)); } -MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path, const ProtocolOption &option) { - setup(vhost, app, stream_id, file_path, option); +MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { + setup(vhost, app, stream_id, file_path, option, std::move(poller)); } -void MP4Reader::setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option) { +void MP4Reader::setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { //读写文件建议放在后台线程 auto tuple = MediaTuple{vhost, app, stream_id}; - _poller = WorkThreadPool::Instance().getPoller(); + _poller = poller ? std::move(poller) : WorkThreadPool::Instance().getPoller(); _file_path = file_path; if (_file_path.empty()) { GET_CONFIG(string, recordPath, Protocol::kMP4SavePath); @@ -122,6 +124,7 @@ void MP4Reader::stopReadMP4() { void MP4Reader::startReadMP4(uint64_t sample_ms, bool ref_self, bool file_repeat) { GET_CONFIG(uint32_t, sampleMS, Record::kSampleMS); + setCurrentStamp(0); auto strong_self = shared_from_this(); if (_muxer) { //一直读到所有track就绪为止 diff --git a/src/Record/MP4Reader.h b/src/Record/MP4Reader.h index ac07e9e8..c97c4862 100644 --- a/src/Record/MP4Reader.h +++ b/src/Record/MP4Reader.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -29,12 +29,10 @@ public: * @param file_path 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 */ MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, - const std::string &file_path = ""); + const std::string &file_path = "", toolkit::EventPoller::Ptr poller = nullptr); MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, - const std::string &file_path, const ProtocolOption &option); - - ~MP4Reader() override = default; + const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller = nullptr); /** * 开始解复用MP4文件 @@ -71,7 +69,7 @@ private: void setCurrentStamp(uint32_t stamp); bool seekTo(uint32_t stamp_seek); - void setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option); + void setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller); private: bool _file_repeat = false; diff --git a/src/Record/MP4Recorder.cpp b/src/Record/MP4Recorder.cpp index 59a0d590..f54c1d42 100644 --- a/src/Record/MP4Recorder.cpp +++ b/src/Record/MP4Recorder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -85,10 +85,10 @@ void MP4Recorder::asyncClose() { TraceL << "Closed tmp mp4 file: " << full_path_tmp; if (!full_path_tmp.empty()) { // 获取文件大小 - info.file_size = File::fileSize(full_path_tmp.data()); + info.file_size = File::fileSize(full_path_tmp); if (info.file_size < 1024) { // 录像文件太小,删除之 - File::delete_file(full_path_tmp.data()); + File::delete_file(full_path_tmp); return; } // 临时文件名改成正式文件名,防止mp4未完成时被访问 diff --git a/src/Record/MP4Recorder.h b/src/Record/MP4Recorder.h index 3e0c8013..7b9deb65 100644 --- a/src/Record/MP4Recorder.h +++ b/src/Record/MP4Recorder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Record/MPEG.cpp b/src/Record/MPEG.cpp index 153fd796..ef844277 100644 --- a/src/Record/MPEG.cpp +++ b/src/Record/MPEG.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -18,7 +18,7 @@ using namespace toolkit; -namespace mediakit{ +namespace mediakit { MpegMuxer::MpegMuxer(bool is_ps) { _is_ps = is_ps; @@ -30,67 +30,57 @@ MpegMuxer::~MpegMuxer() { releaseContext(); } -#define XX(name, type, value, str, mpeg_id) \ - case name: { \ - if (mpeg_id == PSI_STREAM_RESERVED) { \ - break; \ - } \ - if (track->getTrackType() == TrackVideo) { \ - _have_video = true; \ - } \ - _codec_to_trackid[track->getCodecId()] = mpeg_muxer_add_stream((::mpeg_muxer_t *)_context, mpeg_id, nullptr, 0); \ - return true; \ - } bool MpegMuxer::addTrack(const Track::Ptr &track) { - switch (track->getCodecId()) { - CODEC_MAP(XX) - default: break; - } - WarnL << "不支持该编码格式,已忽略:" << track->getCodecName(); - return false; -} -#undef XX - -bool MpegMuxer::inputFrame(const Frame::Ptr &frame) { - auto it = _codec_to_trackid.find(frame->getCodecId()); - if (it == _codec_to_trackid.end()) { + auto mpeg_id = getMpegIdByCodec(track->getCodecId()); + if (mpeg_id == PSI_STREAM_RESERVED) { + WarnL << "Unsupported codec: " << track->getCodecName(); return false; } - auto track_id = it->second; + + if (track->getTrackType() == TrackVideo) { + _have_video = true; + } + _tracks[track->getIndex()].track_id = mpeg_muxer_add_stream((::mpeg_muxer_t *)_context, mpeg_id, nullptr, 0); + return true; +} + +bool MpegMuxer::inputFrame(const Frame::Ptr &frame) { + auto it = _tracks.find(frame->getIndex()); + if (it == _tracks.end()) { + return false; + } + auto &track = it->second; _key_pos = !_have_video; switch (frame->getCodecId()) { case CodecH264: case CodecH265: { - //这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理, - return _frame_merger.inputFrame(frame,[this, track_id](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) { + // 这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理, + return track.merger.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) { _key_pos = have_idr; - //取视频时间戳为TS的时间戳 + // 取视频时间戳为TS的时间戳 _timestamp = dts; _max_cache_size = 512 + 1.2 * buffer->size(); - mpeg_muxer_input((::mpeg_muxer_t *)_context, track_id, have_idr ? 0x0001 : 0, pts * 90LL,dts * 90LL, buffer->data(), buffer->size()); + mpeg_muxer_input((::mpeg_muxer_t *)_context, track.track_id, have_idr ? 0x0001 : 0, pts * 90LL, dts * 90LL, buffer->data(), buffer->size()); flushCache(); }); } case CodecAAC: { - if (frame->prefixSize() == 0) { - WarnL << "必须提供adts头才能mpeg-ts打包"; - return false; - } + CHECK(frame->prefixSize(), "Mpeg muxer required aac frame with adts heade"); } default: { if (!_have_video) { - //没有视频时,才以音频时间戳为TS的时间戳 + // 没有视频时,才以音频时间戳为TS的时间戳 _timestamp = frame->dts(); } - if(frame->getTrackType() == TrackType::TrackVideo){ + if (frame->getTrackType() == TrackType::TrackVideo) { _key_pos = frame->keyFrame(); _timestamp = frame->dts(); } _max_cache_size = 512 + 1.2 * frame->size(); - mpeg_muxer_input((::mpeg_muxer_t *)_context, track_id, frame->keyFrame() ? 0x0001 : 0, frame->pts() * 90LL, frame->dts() * 90LL, frame->data(), frame->size()); + mpeg_muxer_input((::mpeg_muxer_t *)_context, track.track_id, frame->keyFrame() ? 0x0001 : 0, frame->pts() * 90LL, frame->dts() * 90LL, frame->data(), frame->size()); flushCache(); return true; } @@ -113,7 +103,6 @@ void MpegMuxer::createContext() { if (!thiz->_current_buffer || thiz->_current_buffer->size() + bytes > thiz->_current_buffer->getCapacity()) { if (thiz->_current_buffer) { - //WarnL << "need realloc mpeg buffer" << thiz->_current_buffer->size() + bytes << " > " << thiz->_current_buffer->getCapacity(); thiz->flushCache(); } thiz->_current_buffer = thiz->_buffer_pool.obtain2(); @@ -153,12 +142,13 @@ void MpegMuxer::releaseContext() { mpeg_muxer_destroy((::mpeg_muxer_t *)_context); _context = nullptr; } - _codec_to_trackid.clear(); - _frame_merger.clear(); + _tracks.clear(); } void MpegMuxer::flush() { - _frame_merger.flush(); + for (auto &pr : _tracks) { + pr.second.merger.flush(); + } } }//mediakit diff --git a/src/Record/MPEG.h b/src/Record/MPEG.h index 567d1b74..dc07af4a 100644 --- a/src/Record/MPEG.h +++ b/src/Record/MPEG.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -70,8 +70,17 @@ private: uint32_t _max_cache_size = 0; uint64_t _timestamp = 0; struct mpeg_muxer_t *_context = nullptr; - std::unordered_map _codec_to_trackid; - FrameMerger _frame_merger{FrameMerger::h264_prefix}; + + class FrameMergerImp : public FrameMerger { + public: + FrameMergerImp() : FrameMerger(FrameMerger::h264_prefix) {} + }; + + struct MP4Track { + int track_id = -1; + FrameMergerImp merger; + }; + std::unordered_map _tracks; toolkit::BufferRaw::Ptr _current_buffer; toolkit::ResourcePool _buffer_pool; }; @@ -87,7 +96,6 @@ namespace mediakit { class MpegMuxer : public MediaSinkInterface { public: MpegMuxer(bool is_ps = false) {} - ~MpegMuxer() override = default; bool addTrack(const Track::Ptr &track) override { return false; } void resetTracks() override {} bool inputFrame(const Frame::Ptr &frame) override { return false; } diff --git a/src/Record/Recorder.cpp b/src/Record/Recorder.cpp index 6183ff1c..2d67fd16 100644 --- a/src/Record/Recorder.cpp +++ b/src/Record/Recorder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -98,22 +98,22 @@ std::shared_ptr Recorder::createRecorder(type type, const Me } case Recorder::type_hls_fmp4: { -#if defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) auto path = Recorder::getRecordPath(type, tuple, option.hls_save_path); GET_CONFIG(bool, enable_vhost, General::kEnableVhost); auto ret = std::make_shared(path, enable_vhost ? string(VHOST_KEY) + "=" + tuple.vhost : "", option); ret->setMediaSource(tuple); return ret; #else - throw std::invalid_argument("hls.fmp4相关功能未打开,请开启ENABLE_HLS_FMP4宏后编译再测试"); + throw std::invalid_argument("hls.fmp4相关功能未打开,请开启ENABLE_MP4宏后编译再测试"); #endif } case Recorder::type_fmp4: { -#if defined(ENABLE_HLS_FMP4) || defined(ENABLE_MP4) +#if defined(ENABLE_MP4) return std::make_shared(tuple, option); #else - throw std::invalid_argument("fmp4相关功能未打开,请开启ENABLE_HLS_FMP4或ENABLE_MP4宏后编译再测试"); + throw std::invalid_argument("fmp4相关功能未打开,请开启ENABLE_MP4宏后编译再测试"); #endif } diff --git a/src/Record/Recorder.h b/src/Record/Recorder.h index 42763b32..57f439cd 100644 --- a/src/Record/Recorder.h +++ b/src/Record/Recorder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtcp/Rtcp.cpp b/src/Rtcp/Rtcp.cpp index a31df64d..dd60492f 100644 --- a/src/Rtcp/Rtcp.cpp +++ b/src/Rtcp/Rtcp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -242,8 +242,6 @@ vector RtcpHeader::loadFromBytes(char *data, size_t len) { class BufferRtcp : public Buffer { public: BufferRtcp(std::shared_ptr rtcp) { _rtcp = std::move(rtcp); } - ~BufferRtcp() override = default; - char *data() const override { return (char *)_rtcp.get(); } size_t size() const override { return _rtcp->getSize(); } diff --git a/src/Rtcp/Rtcp.h b/src/Rtcp/Rtcp.h index 3511f4a6..53e6340c 100644 --- a/src/Rtcp/Rtcp.h +++ b/src/Rtcp/Rtcp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtcp/RtcpContext.cpp b/src/Rtcp/RtcpContext.cpp index 6d4469b4..64de2519 100644 --- a/src/Rtcp/RtcpContext.cpp +++ b/src/Rtcp/RtcpContext.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtcp/RtcpContext.h b/src/Rtcp/RtcpContext.h index 79920311..f80b2efe 100644 --- a/src/Rtcp/RtcpContext.h +++ b/src/Rtcp/RtcpContext.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtcp/RtcpFCI.cpp b/src/Rtcp/RtcpFCI.cpp index 8ed27670..9683f46f 100644 --- a/src/Rtcp/RtcpFCI.cpp +++ b/src/Rtcp/RtcpFCI.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -432,7 +432,7 @@ FCI_TWCC::TwccPacketStatus FCI_TWCC::getPacketChunkList(size_t total_size) const CHECK(ptr < end); auto seq = getBaseSeq(); auto rtp_count = getPacketCount(); - for (uint8_t i = 0; i < rtp_count;) { + for (uint16_t i = 0; i < rtp_count;) { CHECK(ptr + RunLengthChunk::kSize <= end); RunLengthChunk *chunk = (RunLengthChunk *)ptr; if (!chunk->type) { diff --git a/src/Rtcp/RtcpFCI.h b/src/Rtcp/RtcpFCI.h index 5ce36aa2..10d2f558 100644 --- a/src/Rtcp/RtcpFCI.h +++ b/src/Rtcp/RtcpFCI.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/FlvMuxer.cpp b/src/Rtmp/FlvMuxer.cpp index b2d1a6ad..5917f3a0 100644 --- a/src/Rtmp/FlvMuxer.cpp +++ b/src/Rtmp/FlvMuxer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -174,7 +174,7 @@ void FlvRecorder::startRecord(const EventPoller::Ptr &poller, const RtmpMediaSou } }); //新建文件 - _file.reset(File::create_file(file_path.data(), "wb"), [fileBuf](FILE *fp) { + _file.reset(File::create_file(file_path, "wb"), [fileBuf](FILE *fp) { if (fp) { fflush(fp); fclose(fp); diff --git a/src/Rtmp/FlvMuxer.h b/src/Rtmp/FlvMuxer.h index 4adc68d9..01e34a82 100644 --- a/src/Rtmp/FlvMuxer.h +++ b/src/Rtmp/FlvMuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -47,8 +47,6 @@ private: class FlvRecorder : public FlvMuxer , public std::enable_shared_from_this{ public: using Ptr = std::shared_ptr; - FlvRecorder() = default; - ~FlvRecorder() override = default; void startRecord(const toolkit::EventPoller::Ptr &poller, const RtmpMediaSource::Ptr &media, const std::string &file_path); void startRecord(const toolkit::EventPoller::Ptr &poller, const std::string &vhost, const std::string &app, const std::string &stream, const std::string &file_path); diff --git a/src/Rtmp/FlvPlayer.cpp b/src/Rtmp/FlvPlayer.cpp index 3724a219..1a54f69e 100644 --- a/src/Rtmp/FlvPlayer.cpp +++ b/src/Rtmp/FlvPlayer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/FlvPlayer.h b/src/Rtmp/FlvPlayer.h index 2e79dac2..12ba54e3 100644 --- a/src/Rtmp/FlvPlayer.h +++ b/src/Rtmp/FlvPlayer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,7 +20,6 @@ namespace mediakit { class FlvPlayer : public PlayerBase, public HttpClientImp, private FlvSplitter { public: FlvPlayer(const toolkit::EventPoller::Ptr &poller); - ~FlvPlayer() override = default; void play(const std::string &url) override; void teardown() override; diff --git a/src/Rtmp/FlvSplitter.cpp b/src/Rtmp/FlvSplitter.cpp index 3e99d9ef..732c9a31 100644 --- a/src/Rtmp/FlvSplitter.cpp +++ b/src/Rtmp/FlvSplitter.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/FlvSplitter.h b/src/Rtmp/FlvSplitter.h index 78f2d1d5..cde80d82 100644 --- a/src/Rtmp/FlvSplitter.h +++ b/src/Rtmp/FlvSplitter.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -18,10 +18,6 @@ namespace mediakit { class FlvSplitter : public HttpRequestSplitter { -public: - FlvSplitter() = default; - ~FlvSplitter() = default; - protected: void onRecvContent(const char *data,size_t len) override; ssize_t onRecvHeader(const char *data,size_t len) override; diff --git a/src/Rtmp/Rtmp.cpp b/src/Rtmp/Rtmp.cpp index 33c46f11..83e2a4fd 100644 --- a/src/Rtmp/Rtmp.cpp +++ b/src/Rtmp/Rtmp.cpp @@ -1,14 +1,15 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "Rtmp.h" +#include "Common/config.h" #include "Extension/Factory.h" namespace mediakit { @@ -35,8 +36,7 @@ VideoMeta::VideoMeta(const VideoTrack::Ptr &video) { if (video->getBitRate()) { _metadata.set("videodatarate", video->getBitRate() / 1024); } - _codecId = video->getCodecId(); - _metadata.set("videocodecid", Factory::getAmfByCodecId(_codecId)); + _metadata.set("videocodecid", Factory::getAmfByCodecId(video->getCodecId())); } AudioMeta::AudioMeta(const AudioTrack::Ptr &audio) { @@ -52,8 +52,7 @@ AudioMeta::AudioMeta(const AudioTrack::Ptr &audio) { if (audio->getAudioChannel() > 0) { _metadata.set("stereo", audio->getAudioChannel() > 1); } - _codecId = audio->getCodecId(); - _metadata.set("audiocodecid", Factory::getAmfByCodecId(_codecId)); + _metadata.set("audiocodecid", Factory::getAmfByCodecId(audio->getCodecId())); } uint8_t getAudioRtmpFlags(const Track::Ptr &track) { @@ -259,36 +258,6 @@ void RtmpHandshake::random_generate(char *bytes, int size) { } } -#pragma pack(push, 1) - -struct RtmpVideoHeaderEnhanced { -#if __BYTE_ORDER == __BIG_ENDIAN - uint8_t enhanced : 1; - uint8_t frame_type : 3; - uint8_t pkt_type : 4; - uint32_t fourcc; -#else - uint8_t pkt_type : 4; - uint8_t frame_type : 3; - uint8_t enhanced : 1; - uint32_t fourcc; -#endif -}; - -struct RtmpVideoHeaderClassic { -#if __BYTE_ORDER == __BIG_ENDIAN - uint8_t frame_type : 4; - uint8_t codec_id : 4; - uint8_t h264_pkt_type; -#else - uint8_t codec_id : 4; - uint8_t frame_type : 4; - uint8_t h264_pkt_type; -#endif -}; - -#pragma pack(pop) - CodecId parseVideoRtmpPacket(const uint8_t *data, size_t size, RtmpPacketInfo *info) { RtmpPacketInfo save; info = info ? info : &save; @@ -298,7 +267,7 @@ CodecId parseVideoRtmpPacket(const uint8_t *data, size_t size, RtmpPacketInfo *i RtmpVideoHeaderEnhanced *enhanced_header = (RtmpVideoHeaderEnhanced *)data; if (enhanced_header->enhanced) { // IsExHeader == 1 - CHECK(size >= 5, "Invalid rtmp buffer size: ", size); + CHECK(size > RtmpPacketInfo::kEnhancedRtmpHeaderSize, "Invalid rtmp buffer size: ", size); info->is_enhanced = true; info->video.frame_type = (RtmpFrameType)(enhanced_header->frame_type); info->video.pkt_type = (RtmpPacketType)(enhanced_header->pkt_type); diff --git a/src/Rtmp/Rtmp.h b/src/Rtmp/Rtmp.h index 66908af2..ec87892e 100644 --- a/src/Rtmp/Rtmp.h +++ b/src/Rtmp/Rtmp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -132,6 +132,32 @@ public: uint8_t streamid[3] = {0}; /* Always 0. */ }; +struct RtmpVideoHeaderEnhanced { +#if __BYTE_ORDER == __BIG_ENDIAN + uint8_t enhanced : 1; + uint8_t frame_type : 3; + uint8_t pkt_type : 4; + uint32_t fourcc; +#else + uint8_t pkt_type : 4; + uint8_t frame_type : 3; + uint8_t enhanced : 1; + uint32_t fourcc; +#endif +}; + +struct RtmpVideoHeaderClassic { +#if __BYTE_ORDER == __BIG_ENDIAN + uint8_t frame_type : 4; + uint8_t codec_id : 4; + uint8_t h264_pkt_type; +#else + uint8_t codec_id : 4; + uint8_t frame_type : 4; + uint8_t h264_pkt_type; +#endif +}; + #pragma pack(pop) class RtmpPacket : public toolkit::Buffer{ @@ -188,17 +214,17 @@ private: /** * rtmp metadata基类,用于描述rtmp格式信息 */ -class Metadata : public CodecInfo{ +class Metadata { public: using Ptr = std::shared_ptr; Metadata(): _metadata(AMF_OBJECT) {} - virtual ~Metadata() = default; const AMFValue &getMetadata() const{ return _metadata; } static void addTrack(AMFValue &metadata, const Track::Ptr &track); + protected: AMFValue _metadata; }; @@ -206,7 +232,7 @@ protected: /** * metadata中除音视频外的其他描述部分 */ -class TitleMeta : public Metadata{ +class TitleMeta : public Metadata { public: using Ptr = std::shared_ptr; @@ -214,37 +240,20 @@ public: size_t fileSize = 0, const std::map &header = std::map()); - CodecId getCodecId() const override{ - return CodecInvalid; - } }; -class VideoMeta : public Metadata{ +class VideoMeta : public Metadata { public: using Ptr = std::shared_ptr; VideoMeta(const VideoTrack::Ptr &video); - virtual ~VideoMeta() = default; - - CodecId getCodecId() const override{ - return _codecId; - } -private: - CodecId _codecId; }; -class AudioMeta : public Metadata{ +class AudioMeta : public Metadata { public: using Ptr = std::shared_ptr; AudioMeta(const AudioTrack::Ptr &audio); - virtual ~AudioMeta() = default; - - CodecId getCodecId() const override{ - return _codecId; - } -private: - CodecId _codecId; }; //根据音频track获取flags @@ -353,6 +362,8 @@ enum class RtmpAACPacketType : uint8_t { //////////////////////////////////////////// struct RtmpPacketInfo { + enum { kEnhancedRtmpHeaderSize = sizeof(RtmpVideoHeaderEnhanced) }; + CodecId codec = CodecInvalid; bool is_enhanced; union { diff --git a/src/Rtmp/RtmpCodec.h b/src/Rtmp/RtmpCodec.h index 67c9ce92..a01f1f63 100644 --- a/src/Rtmp/RtmpCodec.h +++ b/src/Rtmp/RtmpCodec.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -22,20 +22,12 @@ public: using Ptr = std::shared_ptr; using RingType = toolkit::RingBuffer; - RtmpRing() = default; virtual ~RtmpRing() = default; - /** - * 获取rtmp环形缓存 - */ - virtual RingType::Ptr getRtmpRing() const { - return _ring; - } - /** * 设置rtmp环形缓存 */ - virtual void setRtmpRing(const RingType::Ptr &ring) { + void setRtmpRing(const RingType::Ptr &ring) { _ring = ring; } @@ -53,12 +45,19 @@ protected: RingType::Ptr _ring; }; -class RtmpCodec : public RtmpRing, public FrameDispatcher, public CodecInfo { +class RtmpCodec : public RtmpRing, public FrameWriterInterface { public: using Ptr = std::shared_ptr; - RtmpCodec() = default; - ~RtmpCodec() override = default; - virtual void makeConfigPacket() {}; + RtmpCodec(Track::Ptr track) { _track = std::move(track); } + + virtual void makeConfigPacket() {} + + bool inputFrame(const Frame::Ptr &frame) override { return _track->inputFrame(frame); } + + const Track::Ptr &getTrack() const { return _track; } + +private: + Track::Ptr _track; }; diff --git a/src/Rtmp/RtmpDemuxer.cpp b/src/Rtmp/RtmpDemuxer.cpp index 20d8f052..151f6958 100644 --- a/src/Rtmp/RtmpDemuxer.cpp +++ b/src/Rtmp/RtmpDemuxer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -146,15 +146,13 @@ void RtmpDemuxer::makeVideoTrack(const Track::Ptr &track, int bit_rate) { return; } // 生成rtmpCodec对象以便解码rtmp - _video_rtmp_decoder = Factory::getRtmpCodecByTrack(_video_track, false); + _video_rtmp_decoder = Factory::getRtmpDecoderByTrack(_video_track); if (!_video_rtmp_decoder) { // 找不到相应的rtmp解码器,该track无效 _video_track.reset(); return; } _video_track->setBitRate(bit_rate); - // 设置rtmp解码器代理,生成的frame写入该Track - _video_rtmp_decoder->addDelegate(_video_track); addTrack(_video_track); _try_get_video_track = true; } @@ -169,15 +167,13 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec, int sample_rate, in return; } // 生成rtmpCodec对象以便解码rtmp - _audio_rtmp_decoder = Factory::getRtmpCodecByTrack(_audio_track, false); + _audio_rtmp_decoder = Factory::getRtmpDecoderByTrack(_audio_track); if (!_audio_rtmp_decoder) { // 找不到相应的rtmp解码器,该track无效 _audio_track.reset(); return; } _audio_track->setBitRate(bit_rate); - // 设置rtmp解码器代理,生成的frame写入该Track - _audio_rtmp_decoder->addDelegate(_audio_track); addTrack(_audio_track); _try_get_audio_track = true; } diff --git a/src/Rtmp/RtmpDemuxer.h b/src/Rtmp/RtmpDemuxer.h index 4cf0412b..85f358ed 100644 --- a/src/Rtmp/RtmpDemuxer.h +++ b/src/Rtmp/RtmpDemuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -24,9 +24,6 @@ class RtmpDemuxer : public Demuxer { public: using Ptr = std::shared_ptr; - RtmpDemuxer() = default; - ~RtmpDemuxer() override = default; - static size_t trackCount(const AMFValue &metadata); bool loadMetaData(const AMFValue &metadata); diff --git a/src/Rtmp/RtmpMediaSource.h b/src/Rtmp/RtmpMediaSource.h index 732cbb85..eb1e3ded 100644 --- a/src/Rtmp/RtmpMediaSource.h +++ b/src/Rtmp/RtmpMediaSource.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/RtmpMediaSourceImp.cpp b/src/Rtmp/RtmpMediaSourceImp.cpp index 4a6f8975..ff5320e6 100644 --- a/src/Rtmp/RtmpMediaSourceImp.cpp +++ b/src/Rtmp/RtmpMediaSourceImp.cpp @@ -105,7 +105,11 @@ void RtmpMediaSourceImp::onWrite(RtmpPacket::Ptr pkt, bool /*= true*/) { // 未获取到所有Track后,或者开启转协议,那么需要解复用rtmp _demuxer->inputRtmp(pkt); } - RtmpMediaSource::onWrite(std::move(pkt)); + GET_CONFIG(bool, directProxy, Rtmp::kDirectProxy); + if (directProxy) { + //直接代理模式才直接使用原始rtmp + RtmpMediaSource::onWrite(std::move(pkt)); + } } int RtmpMediaSourceImp::totalReaderCount() { @@ -113,10 +117,9 @@ int RtmpMediaSourceImp::totalReaderCount() { } void RtmpMediaSourceImp::setProtocolOption(const ProtocolOption &option) { - // 不重复生成rtmp + GET_CONFIG(bool, direct_proxy, Rtmp::kDirectProxy); _option = option; - // 不重复生成rtmp协议 - _option.enable_rtmp = false; + _option.enable_rtmp = !direct_proxy; _muxer = std::make_shared(_tuple, _demuxer->getDuration(), _option); _muxer->setMediaListener(getListener()); _muxer->setTrackListener(std::static_pointer_cast(shared_from_this())); diff --git a/src/Rtmp/RtmpMediaSourceImp.h b/src/Rtmp/RtmpMediaSourceImp.h index 31fa24fe..31857c65 100644 --- a/src/Rtmp/RtmpMediaSourceImp.h +++ b/src/Rtmp/RtmpMediaSourceImp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -37,8 +37,6 @@ public: */ RtmpMediaSourceImp(const MediaTuple& tuple, int ringSize = RTMP_GOP_SIZE); - ~RtmpMediaSourceImp() override = default; - /** * 设置metadata */ diff --git a/src/Rtmp/RtmpMediaSourceMuxer.h b/src/Rtmp/RtmpMediaSourceMuxer.h index 3f6b8bd4..6572fae5 100644 --- a/src/Rtmp/RtmpMediaSourceMuxer.h +++ b/src/Rtmp/RtmpMediaSourceMuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/RtmpMuxer.cpp b/src/Rtmp/RtmpMuxer.cpp index 4be4ac5d..5a5e8b2d 100644 --- a/src/Rtmp/RtmpMuxer.cpp +++ b/src/Rtmp/RtmpMuxer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -14,47 +14,56 @@ namespace mediakit { RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) { - if(!title){ + if (!title) { _metadata = std::make_shared()->getMetadata(); - }else{ + } else { _metadata = title->getMetadata(); } _rtmp_ring = std::make_shared(); } bool RtmpMuxer::addTrack(const Track::Ptr &track) { - auto &encoder = _encoder[track->getTrackType()]; - //生成rtmp编码器,克隆该Track,防止循环引用 - encoder = Factory::getRtmpCodecByTrack(track->clone(), true); + if (_track_existed[track->getTrackType()]) { + // rtmp不支持多个同类型track + WarnL << "Already add a track kind of: " << track->getTrackTypeStr() << ", ignore track: " << track->getCodecName(); + return false; + } + + auto &encoder = _encoders[track->getIndex()]; + CHECK(!encoder); + encoder = Factory::getRtmpEncoderByTrack(track); if (!encoder) { return false; } - //设置rtmp输出环形缓存 + // 标记已经存在该类型track + _track_existed[track->getTrackType()] = true; + + // 设置rtmp输出环形缓存 encoder->setRtmpRing(_rtmp_ring); - //添加metadata + // 添加metadata Metadata::addTrack(_metadata, track); return true; } bool RtmpMuxer::inputFrame(const Frame::Ptr &frame) { - auto &encoder = _encoder[frame->getTrackType()]; + auto &encoder = _encoders[frame->getIndex()]; return encoder ? encoder->inputFrame(frame) : false; } void RtmpMuxer::flush() { - for (auto &encoder : _encoder) { - if (encoder) { - encoder->flush(); + for (auto &pr : _encoders) { + if (pr.second) { + pr.second->flush(); } } } -void RtmpMuxer::makeConfigPacket(){ - for(auto &encoder : _encoder){ - if(encoder){ - encoder->makeConfigPacket(); +void RtmpMuxer::makeConfigPacket() { + for (auto &pr : _encoders) { + if (pr.second) { + pr.second->makeConfigPacket(); } } } @@ -69,10 +78,8 @@ RtmpRing::RingType::Ptr RtmpMuxer::getRtmpRing() const { void RtmpMuxer::resetTracks() { _metadata.clear(); - for(auto &encoder : _encoder){ - encoder = nullptr; - } + _encoders.clear(); + CLEAR_ARR(_track_existed); } - -}/* namespace mediakit */ \ No newline at end of file +} /* namespace mediakit */ \ No newline at end of file diff --git a/src/Rtmp/RtmpMuxer.h b/src/Rtmp/RtmpMuxer.h index 430166c2..d029a632 100644 --- a/src/Rtmp/RtmpMuxer.h +++ b/src/Rtmp/RtmpMuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -26,7 +26,6 @@ public: * 构造函数 */ RtmpMuxer(const TitleMeta::Ptr &title); - ~RtmpMuxer() override = default; /** * 获取完整的SDP字符串 @@ -65,10 +64,13 @@ public: * 生成config包 */ void makeConfigPacket(); + private: - RtmpRing::RingType::Ptr _rtmp_ring; + bool _track_existed[2] = { false, false }; + AMFValue _metadata; - RtmpCodec::Ptr _encoder[TrackMax]; + RtmpRing::RingType::Ptr _rtmp_ring; + std::unordered_map _encoders; }; diff --git a/src/Rtmp/RtmpPlayer.cpp b/src/Rtmp/RtmpPlayer.cpp index 4f2239ba..abc45387 100644 --- a/src/Rtmp/RtmpPlayer.cpp +++ b/src/Rtmp/RtmpPlayer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/RtmpPlayer.h b/src/Rtmp/RtmpPlayer.h index 75abf7f9..ccac9360 100644 --- a/src/Rtmp/RtmpPlayer.h +++ b/src/Rtmp/RtmpPlayer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/RtmpPlayerImp.h b/src/Rtmp/RtmpPlayerImp.h index ecf9a34f..ddcf469f 100644 --- a/src/Rtmp/RtmpPlayerImp.h +++ b/src/Rtmp/RtmpPlayerImp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/RtmpProtocol.cpp b/src/Rtmp/RtmpProtocol.cpp index 386f5205..010e30d4 100644 --- a/src/Rtmp/RtmpProtocol.cpp +++ b/src/Rtmp/RtmpProtocol.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -187,8 +187,6 @@ public: _size = size; } - ~BufferPartial() override = default; - char *data() const override { return _data; } diff --git a/src/Rtmp/RtmpProtocol.h b/src/Rtmp/RtmpProtocol.h index c509641f..7ace93eb 100644 --- a/src/Rtmp/RtmpProtocol.h +++ b/src/Rtmp/RtmpProtocol.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/RtmpPusher.cpp b/src/Rtmp/RtmpPusher.cpp index 79de34b3..92363241 100644 --- a/src/Rtmp/RtmpPusher.cpp +++ b/src/Rtmp/RtmpPusher.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/RtmpPusher.h b/src/Rtmp/RtmpPusher.h index 0b9cdb89..e74012ee 100644 --- a/src/Rtmp/RtmpPusher.h +++ b/src/Rtmp/RtmpPusher.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/RtmpSession.cpp b/src/Rtmp/RtmpSession.cpp index fd09141f..1e22f32c 100644 --- a/src/Rtmp/RtmpSession.cpp +++ b/src/Rtmp/RtmpSession.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -23,8 +23,6 @@ RtmpSession::RtmpSession(const Socket::Ptr &sock) : Session(sock) { sock->setSendTimeOutSecond(keep_alive_sec); } -RtmpSession::~RtmpSession() = default; - void RtmpSession::onError(const SockException& err) { bool is_player = !_push_src_ownership; uint64_t duration = _ticker.createdTime() / 1000; diff --git a/src/Rtmp/RtmpSession.h b/src/Rtmp/RtmpSession.h index f51b567e..754b2609 100644 --- a/src/Rtmp/RtmpSession.h +++ b/src/Rtmp/RtmpSession.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -27,7 +27,6 @@ public: using Ptr = std::shared_ptr; RtmpSession(const toolkit::Socket::Ptr &sock); - ~RtmpSession() override; void onRecv(const toolkit::Buffer::Ptr &buf) override; void onError(const toolkit::SockException &err) override; diff --git a/src/Rtmp/amf.cpp b/src/Rtmp/amf.cpp index 8ffcf5d5..b93fa2ce 100644 --- a/src/Rtmp/amf.cpp +++ b/src/Rtmp/amf.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/amf.h b/src/Rtmp/amf.h index 276315cf..c3f7ed29 100644 --- a/src/Rtmp/amf.h +++ b/src/Rtmp/amf.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/utils.cpp b/src/Rtmp/utils.cpp index 5c251dd9..cb36447f 100644 --- a/src/Rtmp/utils.cpp +++ b/src/Rtmp/utils.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtmp/utils.h b/src/Rtmp/utils.h index 9acad755..3e13a7f8 100644 --- a/src/Rtmp/utils.h +++ b/src/Rtmp/utils.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/Decoder.cpp b/src/Rtp/Decoder.cpp index 37a347ac..65dc655c 100644 --- a/src/Rtp/Decoder.cpp +++ b/src/Rtp/Decoder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -11,11 +11,7 @@ #include "Decoder.h" #include "PSDecoder.h" #include "TSDecoder.h" -#include "Extension/H264.h" -#include "Extension/H265.h" -#include "Extension/AAC.h" -#include "Extension/G711.h" -#include "Extension/Opus.h" +#include "Extension/Factory.h" #if defined(ENABLE_RTPPROXY) || defined(ENABLE_HLS) #include "mpeg-ts.h" @@ -66,7 +62,9 @@ DecoderImp::Ptr DecoderImp::createDecoder(Type type, MediaSinkInterface *sink){ } void DecoderImp::flush() { - _merger.flush(); + for (auto &pr : _tracks) { + pr.second.second.flush(); + } } ssize_t DecoderImp::input(const uint8_t *data, size_t bytes){ @@ -85,164 +83,68 @@ DecoderImp::DecoderImp(const Decoder::Ptr &decoder, MediaSinkInterface *sink){ } #if defined(ENABLE_RTPPROXY) || defined(ENABLE_HLS) -#define SWITCH_CASE(codec_id) case codec_id : return #codec_id -static const char *getCodecName(int codec_id) { - switch (codec_id) { - SWITCH_CASE(PSI_STREAM_MPEG1); - SWITCH_CASE(PSI_STREAM_MPEG2); - SWITCH_CASE(PSI_STREAM_AUDIO_MPEG1); - SWITCH_CASE(PSI_STREAM_MP3); - SWITCH_CASE(PSI_STREAM_AAC); - SWITCH_CASE(PSI_STREAM_MPEG4); - SWITCH_CASE(PSI_STREAM_MPEG4_AAC_LATM); - SWITCH_CASE(PSI_STREAM_H264); - SWITCH_CASE(PSI_STREAM_MPEG4_AAC); - SWITCH_CASE(PSI_STREAM_H265); - SWITCH_CASE(PSI_STREAM_AUDIO_AC3); - SWITCH_CASE(PSI_STREAM_AUDIO_EAC3); - SWITCH_CASE(PSI_STREAM_AUDIO_DTS); - SWITCH_CASE(PSI_STREAM_VIDEO_DIRAC); - SWITCH_CASE(PSI_STREAM_VIDEO_VC1); - SWITCH_CASE(PSI_STREAM_VIDEO_SVAC); - SWITCH_CASE(PSI_STREAM_AUDIO_SVAC); - SWITCH_CASE(PSI_STREAM_AUDIO_G711A); - SWITCH_CASE(PSI_STREAM_AUDIO_G711U); - SWITCH_CASE(PSI_STREAM_AUDIO_G722); - SWITCH_CASE(PSI_STREAM_AUDIO_G723); - SWITCH_CASE(PSI_STREAM_AUDIO_G729); - SWITCH_CASE(PSI_STREAM_AUDIO_OPUS); - default : return "unknown codec"; + +void DecoderImp::onStream(int stream, int codecid, const void *extra, size_t bytes, int finish) { + // G711传统只支持 8000/1/16的规格,FFmpeg貌似做了扩展,但是这里不管它了 + auto track = Factory::getTrackByCodecId(getCodecByMpegId(codecid), 8000, 1, 16); + if (!track) { + return; } -} - -void DecoderImp::onStream(int stream, int codecid, const void *extra, size_t bytes, int finish){ - switch (codecid) { - case PSI_STREAM_H264: { - onTrack(std::make_shared()); - break; - } - - case PSI_STREAM_H265: { - onTrack(std::make_shared()); - break; - } - - case PSI_STREAM_MPEG4_AAC : - case PSI_STREAM_AAC: { - onTrack(std::make_shared()); - break; - } - - case PSI_STREAM_AUDIO_G711A: - case PSI_STREAM_AUDIO_G711U: { - auto codec = codecid == PSI_STREAM_AUDIO_G711A ? CodecG711A : CodecG711U; - //G711传统只支持 8000/1/16的规格,FFmpeg貌似做了扩展,但是这里不管它了 - onTrack(std::make_shared(codec, 8000, 1, 16)); - break; - } - - case PSI_STREAM_AUDIO_OPUS: { - onTrack(std::make_shared()); - break; - } - - default: - if(codecid != 0){ - WarnL<< "unsupported codec type:" << getCodecName(codecid) << " " << (int)codecid; - } - break; - } - - //防止未获取视频track提前complete导致忽略后续视频的问题,用于兼容一些不太规范的ps流 - if (finish && _tracks[TrackVideo] ) { + onTrack(stream, std::move(track)); + // 防止未获取视频track提前complete导致忽略后续视频的问题,用于兼容一些不太规范的ps流 + if (finish && _have_video) { _sink->addTrackCompleted(); - InfoL << "add track finished"; + InfoL << "Add track finished"; } } -void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,size_t bytes) { +void DecoderImp::onDecode(int stream, int codecid, int flags, int64_t pts, int64_t dts, const void *data, size_t bytes) { pts /= 90; dts /= 90; - switch (codecid) { - case PSI_STREAM_H264: { - if (!_tracks[TrackVideo]) { - onTrack(std::make_shared()); - } - auto frame = std::make_shared((char *) data, bytes, (uint64_t)dts, (uint64_t)pts, prefixSize((char *) data, bytes)); - _merger.inputFrame(frame,[this](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) { - onFrame(std::make_shared >(buffer, dts, pts, prefixSize(buffer->data(), buffer->size()), 0)); - }); - break; - } - - case PSI_STREAM_H265: { - if (!_tracks[TrackVideo]) { - onTrack(std::make_shared()); - } - auto frame = std::make_shared((char *) data, bytes, (uint64_t)dts, (uint64_t)pts, prefixSize((char *) data, bytes)); - _merger.inputFrame(frame,[this](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) { - onFrame(std::make_shared >(buffer, dts, pts, prefixSize(buffer->data(), buffer->size()), 0)); - }); - break; - } - - case PSI_STREAM_MPEG4_AAC : - case PSI_STREAM_AAC: { - uint8_t *ptr = (uint8_t *)data; - if(!(bytes > 7 && ptr[0] == 0xFF && (ptr[1] & 0xF0) == 0xF0)){ - //这不是aac - break; - } - if (!_tracks[TrackAudio]) { - onTrack(std::make_shared()); - } - onFrame(std::make_shared(CodecAAC, (char *) data, bytes, (uint64_t)dts, 0, ADTS_HEADER_LEN)); - break; - } - - case PSI_STREAM_AUDIO_G711A: - case PSI_STREAM_AUDIO_G711U: { - auto codec = codecid == PSI_STREAM_AUDIO_G711A ? CodecG711A : CodecG711U; - if (!_tracks[TrackAudio]) { - //G711传统只支持 8000/1/16的规格,FFmpeg貌似做了扩展,但是这里不管它了 - onTrack(std::make_shared(codec, 8000, 1, 16)); - } - onFrame(std::make_shared(codec, (char *) data, bytes, (uint64_t)dts)); - break; - } - - case PSI_STREAM_AUDIO_OPUS: { - if (!_tracks[TrackAudio]) { - onTrack(std::make_shared()); - } - onFrame(std::make_shared(CodecOpus, (char *) data, bytes, (uint64_t)dts)); - break; - } - - default: - // 海康的 PS 流中会有 codecid 为 0xBD 的包 - if (codecid != 0 && codecid != 0xBD) { - WarnL << "unsupported codec type:" << getCodecName(codecid) << " " << (int) codecid; - } - break; + auto codec = getCodecByMpegId(codecid); + if (codec == CodecInvalid) { + return; } + auto &ref = _tracks[stream]; + if (!ref.first) { + onTrack(stream, Factory::getTrackByCodecId(codec, 8000, 1, 16)); + } + auto frame = Factory::getFrameFromPtr(codec, (char *)data, bytes, dts, pts); + if (getTrackType(codec) != TrackVideo) { + onFrame(stream, frame); + return; + } + ref.second.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) { + onFrame(stream, Factory::getFrameFromBuffer(codec, buffer, dts, pts)); + }); } #else void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,size_t bytes) {} void DecoderImp::onStream(int stream,int codecid,const void *extra,size_t bytes,int finish) {} #endif -void DecoderImp::onTrack(const Track::Ptr &track) { - if (!_tracks[track->getTrackType()]) { - _tracks[track->getTrackType()] = track; - _sink->addTrack(track); - InfoL << "got track: " << track->getCodecName(); +void DecoderImp::onTrack(int index, const Track::Ptr &track) { + if (!track) { + return; } + track->setIndex(index); + auto &ref = _tracks[index]; + if (ref.first) { + WarnL << "Already existed a same track: " << index << ", codec: " << track->getCodecName(); + return; + } + ref.first = track; + _sink->addTrack(track); + InfoL << "Got track: " << track->getCodecName(); + _have_video = track->getTrackType() == TrackVideo ? true : _have_video; } -void DecoderImp::onFrame(const Frame::Ptr &frame) { - _sink->inputFrame(frame); +void DecoderImp::onFrame(int index, const Frame::Ptr &frame) { + if (frame) { + frame->setIndex(index); + _sink->inputFrame(frame); + } } }//namespace mediakit diff --git a/src/Rtp/Decoder.h b/src/Rtp/Decoder.h index c6f8aacf..9da460c4 100644 --- a/src/Rtp/Decoder.h +++ b/src/Rtp/Decoder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -37,20 +37,19 @@ protected: onStream _on_stream; }; -class DecoderImp{ +class DecoderImp { public: typedef enum { decoder_ts = 0, decoder_ps } Type; using Ptr = std::shared_ptr; - ~DecoderImp() = default; static Ptr createDecoder(Type type, MediaSinkInterface *sink); ssize_t input(const uint8_t *data, size_t bytes); void flush(); protected: - void onTrack(const Track::Ptr &track); - void onFrame(const Frame::Ptr &frame); + void onTrack(int index, const Track::Ptr &track); + void onFrame(int index, const Frame::Ptr &frame); private: DecoderImp(const Decoder::Ptr &decoder, MediaSinkInterface *sink); @@ -58,10 +57,15 @@ private: void onStream(int stream, int codecid, const void *extra, size_t bytes, int finish); private: + bool _have_video = false; Decoder::Ptr _decoder; MediaSinkInterface *_sink; - FrameMerger _merger{FrameMerger::none}; - Track::Ptr _tracks[TrackMax]; + + class FrameMergerImp : public FrameMerger { + public: + FrameMergerImp() : FrameMerger(FrameMerger::none) {} + }; + std::unordered_map > _tracks; }; }//namespace mediakit diff --git a/src/Rtp/GB28181Process.cpp b/src/Rtp/GB28181Process.cpp index 204d98f8..29c9704f 100644 --- a/src/Rtp/GB28181Process.cpp +++ b/src/Rtp/GB28181Process.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -12,11 +12,6 @@ #include "GB28181Process.h" #include "Extension/CommonRtp.h" #include "Extension/Factory.h" -#include "Extension/G711.h" -#include "Extension/H264.h" -#include "Extension/H265.h" -#include "Extension/Opus.h" -#include "Extension/JPEG.h" #include "Http/HttpTSPlayer.h" #include "Util/File.h" #include "Common/config.h" @@ -45,8 +40,6 @@ public: setNtpStamp(0, 0); } - ~RtpReceiverImp() override = default; - bool inputRtp(TrackType type, uint8_t *ptr, size_t len) { return RtpTrack::inputRtp(type, _sample_rate, ptr, len).operator bool(); } @@ -85,48 +78,58 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) { if (!ref) { if (_rtp_receiver.size() > 2) { // 防止pt类型太多导致内存溢出 - throw std::invalid_argument("rtp pt类型不得超过2种!"); + WarnL << "Rtp payload type more than 2 types: " << _rtp_receiver.size(); } switch (pt) { case Rtsp::PT_PCMA: case Rtsp::PT_PCMU: { // CodecG711U or CodecG711A ref = std::make_shared(8000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); }); - auto track = std::make_shared(pt == Rtsp::PT_PCMU ? CodecG711U : CodecG711A, 8000, 1, 16); + auto track = Factory::getTrackByCodecId(pt == Rtsp::PT_PCMU ? CodecG711U : CodecG711A, 8000, 1, 16); + CHECK(track); + track->setIndex(pt); _interface->addTrack(track); - _rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track); + _rtp_decoder[pt] = Factory::getRtpDecoderByCodecId(track->getCodecId()); break; } case Rtsp::PT_JPEG: { // mjpeg ref = std::make_shared(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); }); - auto track = std::make_shared(); + auto track = Factory::getTrackByCodecId(CodecJPEG); + CHECK(track); + track->setIndex(pt); _interface->addTrack(track); - _rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track); + _rtp_decoder[pt] = Factory::getRtpDecoderByCodecId(track->getCodecId()); break; } default: { if (pt == opus_pt) { // opus负载 ref = std::make_shared(48000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); }); - auto track = std::make_shared(); + auto track = Factory::getTrackByCodecId(CodecOpus); + CHECK(track); + track->setIndex(pt); _interface->addTrack(track); - _rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track); + _rtp_decoder[pt] = Factory::getRtpDecoderByCodecId(track->getCodecId()); } else if (pt == h265_pt) { // H265负载 ref = std::make_shared(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); }); - auto track = std::make_shared(); + auto track = Factory::getTrackByCodecId(CodecH265); + CHECK(track); + track->setIndex(pt); _interface->addTrack(track); - _rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track); + _rtp_decoder[pt] = Factory::getRtpDecoderByCodecId(track->getCodecId()); } else if (pt == h264_pt) { // H264负载 ref = std::make_shared(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); }); - auto track = std::make_shared(); + auto track = Factory::getTrackByCodecId(CodecH264); + CHECK(track); + track->setIndex(pt); _interface->addTrack(track); - _rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track); + _rtp_decoder[pt] = Factory::getRtpDecoderByCodecId(track->getCodecId()); } else { if (pt != Rtsp::PT_MP2T && pt != ps_pt) { - WarnL << "rtp payload type未识别(" << (int)pt << "),已按ts或ps负载处理"; + WarnL << "Unknown rtp payload type(" << (int)pt << "), decode it as mpeg-ps or mpeg-ts"; } ref = std::make_shared(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); }); // ts或ps负载 @@ -146,7 +149,8 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) { } } // 设置frame回调 - _rtp_decoder[pt]->addDelegate([this](const Frame::Ptr &frame) { + _rtp_decoder[pt]->addDelegate([this, pt](const Frame::Ptr &frame) { + frame->setIndex(pt); onRtpDecode(frame); return true; }); diff --git a/src/Rtp/GB28181Process.h b/src/Rtp/GB28181Process.h index 2ab688cf..4cef1e95 100644 --- a/src/Rtp/GB28181Process.h +++ b/src/Rtp/GB28181Process.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -27,7 +27,6 @@ public: using Ptr = std::shared_ptr; GB28181Process(const MediaInfo &media_info, MediaSinkInterface *sink); - ~GB28181Process() override = default; /** * 输入rtp diff --git a/src/Rtp/PSDecoder.cpp b/src/Rtp/PSDecoder.cpp index a9a5beba..f176670a 100644 --- a/src/Rtp/PSDecoder.cpp +++ b/src/Rtp/PSDecoder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/PSDecoder.h b/src/Rtp/PSDecoder.h index c56475ab..db05e282 100644 --- a/src/Rtp/PSDecoder.h +++ b/src/Rtp/PSDecoder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/PSEncoder.cpp b/src/Rtp/PSEncoder.cpp index 78cedb34..66e39bc7 100644 --- a/src/Rtp/PSEncoder.cpp +++ b/src/Rtp/PSEncoder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -12,7 +12,6 @@ #include "PSEncoder.h" #include "Common/config.h" -#include "Extension/H264.h" #include "Extension/CommonRtp.h" #include "Rtsp/RtspMuxer.h" @@ -22,23 +21,23 @@ namespace mediakit{ PSEncoderImp::PSEncoderImp(uint32_t ssrc, uint8_t payload_type) : MpegMuxer(true) { GET_CONFIG(uint32_t,video_mtu,Rtp::kVideoMtuSize); - _rtp_encoder = std::make_shared(CodecInvalid, ssrc, video_mtu, 90000, payload_type, 0); - _rtp_encoder->setRtpRing(std::make_shared()); - _rtp_encoder->getRtpRing()->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key){ - onRTP(std::move(rtp),is_key); - })); - InfoL << this << " " << printSSRC(_rtp_encoder->getSsrc()); + _rtp_encoder = std::make_shared(); + _rtp_encoder->setRtpInfo(ssrc, video_mtu, 90000, payload_type); + auto ring = std::make_shared(); + ring->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), is_key); })); + _rtp_encoder->setRtpRing(std::move(ring)); + InfoL << this << " " << ssrc; } PSEncoderImp::~PSEncoderImp() { - InfoL << this << " " << printSSRC(_rtp_encoder->getSsrc()); + InfoL << this; } void PSEncoderImp::onWrite(std::shared_ptr buffer, uint64_t stamp, bool key_pos) { if (!buffer) { return; } - _rtp_encoder->inputFrame(std::make_shared(buffer->data(), buffer->size(), stamp, stamp,0,key_pos)); + _rtp_encoder->inputFrame(std::make_shared(CodecH264/*只用于识别为视频*/, buffer->data(), buffer->size(), stamp, stamp, 0, key_pos)); } }//namespace mediakit diff --git a/src/Rtp/PSEncoder.h b/src/Rtp/PSEncoder.h index 12a6e639..16bbcd4f 100644 --- a/src/Rtp/PSEncoder.h +++ b/src/Rtp/PSEncoder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -25,7 +25,7 @@ public: protected: //rtp打包后回调 - virtual void onRTP(toolkit::Buffer::Ptr rtp,bool is_key = false) = 0; + virtual void onRTP(toolkit::Buffer::Ptr rtp, bool is_key = false) = 0; protected: void onWrite(std::shared_ptr buffer, uint64_t stamp, bool key_pos) override; diff --git a/src/Rtp/ProcessInterface.h b/src/Rtp/ProcessInterface.h index 6cd7fa9c..b4fd97f4 100644 --- a/src/Rtp/ProcessInterface.h +++ b/src/Rtp/ProcessInterface.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,7 +20,6 @@ namespace mediakit { class ProcessInterface { public: using Ptr = std::shared_ptr; - ProcessInterface() = default; virtual ~ProcessInterface() = default; /** diff --git a/src/Rtp/RawEncoder.cpp b/src/Rtp/RawEncoder.cpp index a4f11ddc..4bc17af7 100644 --- a/src/Rtp/RawEncoder.cpp +++ b/src/Rtp/RawEncoder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -13,6 +13,7 @@ #include "RawEncoder.h" #include "Extension/Factory.h" #include "Rtsp/RtspMuxer.h" +#include "Common//config.h" using namespace toolkit; @@ -30,17 +31,17 @@ RawEncoderImp::~RawEncoderImp() { bool RawEncoderImp::addTrack(const Track::Ptr &track) { if (_send_audio && track->getTrackType() == TrackType::TrackAudio && !_rtp_encoder) { // audio _rtp_encoder = createRtpEncoder(track); - _rtp_encoder->setRtpRing(std::make_shared()); - _rtp_encoder->getRtpRing()->setDelegate(std::make_shared( - [this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), true); })); + auto ring = std::make_shared(); + ring->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), true); })); + _rtp_encoder->setRtpRing(std::move(ring)); return true; } if (!_send_audio && track->getTrackType() == TrackType::TrackVideo && !_rtp_encoder) { _rtp_encoder = createRtpEncoder(track); - _rtp_encoder->setRtpRing(std::make_shared()); - _rtp_encoder->getRtpRing()->setDelegate(std::make_shared( - [this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), is_key); })); + auto ring = std::make_shared(); + ring->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), is_key); })); + _rtp_encoder->setRtpRing(std::move(ring)); return true; } return true; @@ -62,11 +63,17 @@ bool RawEncoderImp::inputFrame(const Frame::Ptr &frame) { } RtpCodec::Ptr RawEncoderImp::createRtpEncoder(const Track::Ptr &track) { - uint32_t sample_rate = 90000; + GET_CONFIG(uint32_t, audio_mtu, Rtp::kAudioMtuSize); + GET_CONFIG(uint32_t, video_mtu, Rtp::kVideoMtuSize); + auto sample_rate = 90000u; + auto mtu = video_mtu; if (track->getTrackType() == TrackType::TrackAudio) { + mtu = audio_mtu; sample_rate = std::static_pointer_cast(track)->getAudioSampleRate(); } - return Factory::getRtpEncoderByCodecId(track->getCodecId(), sample_rate, _payload_type, _ssrc); + auto ret = Factory::getRtpEncoderByCodecId(track->getCodecId(), _payload_type); + ret->setRtpInfo(_ssrc, mtu, sample_rate, _payload_type); + return ret; } } // namespace mediakit diff --git a/src/Rtp/RawEncoder.h b/src/Rtp/RawEncoder.h index 8bc7c98e..71ae12f5 100644 --- a/src/Rtp/RawEncoder.h +++ b/src/Rtp/RawEncoder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/RtpCache.cpp b/src/Rtp/RtpCache.cpp index 0e723b57..75061e05 100644 --- a/src/Rtp/RtpCache.cpp +++ b/src/Rtp/RtpCache.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/RtpCache.h b/src/Rtp/RtpCache.h index a3882222..c8778e18 100644 --- a/src/Rtp/RtpCache.h +++ b/src/Rtp/RtpCache.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -23,7 +23,6 @@ class RtpCache : protected PacketCache { public: using onFlushed = std::function >)>; RtpCache(onFlushed cb); - ~RtpCache() override = default; protected: /** @@ -42,7 +41,6 @@ private: class RtpCachePS : public RtpCache, public PSEncoderImp { public: RtpCachePS(onFlushed cb, uint32_t ssrc, uint8_t payload_type = 96) : RtpCache(std::move(cb)), PSEncoderImp(ssrc, payload_type) {}; - ~RtpCachePS() override = default; void flush() override; protected: @@ -52,7 +50,6 @@ protected: class RtpCacheRaw : public RtpCache, public RawEncoderImp { public: RtpCacheRaw(onFlushed cb, uint32_t ssrc, uint8_t payload_type = 96, bool send_audio = true) : RtpCache(std::move(cb)), RawEncoderImp(ssrc, payload_type, send_audio) {}; - ~RtpCacheRaw() override = default; void flush() override; protected: diff --git a/src/Rtp/RtpProcess.cpp b/src/Rtp/RtpProcess.cpp index 3855f411..c0e16d64 100644 --- a/src/Rtp/RtpProcess.cpp +++ b/src/Rtp/RtpProcess.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -33,7 +33,7 @@ RtpProcess::RtpProcess(const string &stream_id) { GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir); { - FILE *fp = !dump_dir.empty() ? File::create_file(File::absolutePath(_media_info.stream + ".rtp", dump_dir).data(), "wb") : nullptr; + FILE *fp = !dump_dir.empty() ? File::create_file(File::absolutePath(_media_info.stream + ".rtp", dump_dir), "wb") : nullptr; if (fp) { _save_file_rtp.reset(fp, [](FILE *fp) { fclose(fp); @@ -42,7 +42,7 @@ RtpProcess::RtpProcess(const string &stream_id) { } { - FILE *fp = !dump_dir.empty() ? File::create_file(File::absolutePath(_media_info.stream + ".video", dump_dir).data(), "wb") : nullptr; + FILE *fp = !dump_dir.empty() ? File::create_file(File::absolutePath(_media_info.stream + ".video", dump_dir), "wb") : nullptr; if (fp) { _save_file_video.reset(fp, [](FILE *fp) { fclose(fp); @@ -254,8 +254,7 @@ void RtpProcess::emitOnPublish() { return; } if (err.empty()) { - strong_self->_muxer = std::make_shared(strong_self->_media_info, 0.0f, - option); + strong_self->_muxer = std::make_shared(strong_self->_media_info, 0.0f, option); if (strong_self->_only_audio) { strong_self->_muxer->setOnlyAudio(); } @@ -305,4 +304,4 @@ float RtpProcess::getLossRate(MediaSource &sender, TrackType type) { } }//namespace mediakit -#endif//defined(ENABLE_RTPPROXY) +#endif//defined(ENABLE_RTPPROXY) \ No newline at end of file diff --git a/src/Rtp/RtpProcess.h b/src/Rtp/RtpProcess.h index 3e87620a..b9d5009b 100644 --- a/src/Rtp/RtpProcess.h +++ b/src/Rtp/RtpProcess.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/RtpSelector.cpp b/src/Rtp/RtpSelector.cpp index f2ab0d41..8d165124 100644 --- a/src/Rtp/RtpSelector.cpp +++ b/src/Rtp/RtpSelector.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/RtpSelector.h b/src/Rtp/RtpSelector.h index db0683e8..e48622d5 100644 --- a/src/Rtp/RtpSelector.h +++ b/src/Rtp/RtpSelector.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -41,14 +41,10 @@ private: class RtpSelector : public std::enable_shared_from_this{ public: - RtpSelector() = default; - ~RtpSelector() = default; - class ProcessExisted : public std::runtime_error { public: template ProcessExisted(T && ...args) : std::runtime_error(std::forward(args)...) {} - ~ProcessExisted() override = default; }; static bool getSSRC(const char *data,size_t data_len, uint32_t &ssrc); diff --git a/src/Rtp/RtpSender.cpp b/src/Rtp/RtpSender.cpp index 628696fa..28b7770b 100644 --- a/src/Rtp/RtpSender.cpp +++ b/src/Rtp/RtpSender.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -279,7 +279,7 @@ void RtpSender::onSendRtpUdp(const toolkit::Buffer::Ptr &buf, bool check) { return; } auto rtp = static_pointer_cast(buf); - _rtcp_context->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->getStampMS(), 90000 /*not used*/, rtp->size()); + _rtcp_context->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, 90000 /*not used*/, rtp->size()); if (!check) { //减少判断次数 diff --git a/src/Rtp/RtpSender.h b/src/Rtp/RtpSender.h index 304a13f6..0902d12d 100644 --- a/src/Rtp/RtpSender.h +++ b/src/Rtp/RtpSender.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/RtpServer.cpp b/src/Rtp/RtpServer.cpp index 1f71a4a8..51bb5555 100644 --- a/src/Rtp/RtpServer.cpp +++ b/src/Rtp/RtpServer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/RtpServer.h b/src/Rtp/RtpServer.h index 71aa88e7..74250d6f 100644 --- a/src/Rtp/RtpServer.h +++ b/src/Rtp/RtpServer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -31,7 +31,6 @@ public: using onRecv = std::function; enum TcpMode { NONE = 0, PASSIVE, ACTIVE }; - RtpServer() = default; ~RtpServer(); /** diff --git a/src/Rtp/RtpSession.cpp b/src/Rtp/RtpSession.cpp index 70c8dc7a..85f0c2fb 100644 --- a/src/Rtp/RtpSession.cpp +++ b/src/Rtp/RtpSession.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -35,7 +35,8 @@ void RtpSession::setParams(mINI &ini) { _only_audio = ini[kOnlyAudio]; } -RtpSession::RtpSession(const Socket::Ptr &sock) : Session(sock) { +RtpSession::RtpSession(const Socket::Ptr &sock) + : Session(sock) { socklen_t addr_len = sizeof(_addr); getpeername(sock->rawFD(), (struct sockaddr *)&_addr, &addr_len); _is_udp = sock->sockType() == SockNum::Sock_UDP; @@ -46,8 +47,8 @@ RtpSession::RtpSession(const Socket::Ptr &sock) : Session(sock) { } RtpSession::~RtpSession() { - if(_process){ - RtpSelector::Instance().delProcess(_stream_id,_process.get()); + if (_process) { + RtpSelector::Instance().delProcess(_stream_id, _process.get()); } } @@ -64,11 +65,11 @@ void RtpSession::onError(const SockException &err) { } void RtpSession::onManager() { - if(_process && !_process->alive()){ + if (_process && !_process->alive()) { shutdown(SockException(Err_timeout, "receive rtp timeout")); } - if(!_process && _ticker.createdTime() > 10 * 1000){ + if (!_process && _ticker.createdTime() > 10 * 1000) { shutdown(SockException(Err_timeout, "illegal connection")); } } @@ -160,12 +161,12 @@ bool RtpSession::close(MediaSource &sender) { } static const char *findSSRC(const char *data, ssize_t len, uint32_t ssrc) { - //rtp前面必须预留两个字节的长度字段 + // rtp前面必须预留两个字节的长度字段 for (ssize_t i = 2; i <= len - 4; ++i) { - auto ptr = (const uint8_t *) data + i; - if (ptr[0] == (ssrc >> 24) && ptr[1] == ((ssrc >> 16) & 0xFF) && - ptr[2] == ((ssrc >> 8) & 0xFF) && ptr[3] == (ssrc & 0xFF)) { - return (const char *) ptr; + auto ptr = (const uint8_t *)data + i; + if (ptr[0] == (ssrc >> 24) && ptr[1] == ((ssrc >> 16) & 0xFF) && ptr[2] == ((ssrc >> 8) & 0xFF) + && ptr[3] == (ssrc & 0xFF)) { + return (const char *)ptr; } } return nullptr; @@ -173,17 +174,17 @@ static const char *findSSRC(const char *data, ssize_t len, uint32_t ssrc) { static const char *findPsHeaderFlag(const char *data, ssize_t len) { for (ssize_t i = 2; i <= len - 4; ++i) { - auto ptr = (const uint8_t *) data + i; - //PsHeader 0x000001ba、PsSystemHeader0x000001bb(关键帧标识) + auto ptr = (const uint8_t *)data + i; + // PsHeader 0x000001ba、PsSystemHeader0x000001bb(关键帧标识) if (ptr[0] == (0x00) && ptr[1] == (0x00) && ptr[2] == (0x01) && ptr[3] == (0xbb)) { - return (const char *) ptr; + return (const char *)ptr; } } return nullptr; } -//rtp长度到ssrc间的长度固定为10 +// rtp长度到ssrc间的长度固定为10 static size_t constexpr kSSRCOffset = 2 + 4 + 4; // rtp长度到ps header间的长度固定为14 (暂时不采用找ps header,采用找system header代替) // rtp长度到ps system header间的长度固定为20 (关键帧标识) @@ -191,81 +192,80 @@ static size_t constexpr kPSHeaderOffset = 2 + 4 + 4 + 4 + 20; const char *RtpSession::onSearchPacketTail(const char *data, size_t len) { if (!_search_rtp) { - //tcp上下文正常,不用搜索ssrc + // tcp上下文正常,不用搜索ssrc return RtpSplitter::onSearchPacketTail(data, len); } if (!_process) { InfoL << "ssrc未获取到,无法通过ssrc恢复tcp上下文;尝试搜索PsSystemHeader恢复tcp上下文。"; - auto rtp_ptr1 = searchByPsHeaderFlag(data,len); + auto rtp_ptr1 = searchByPsHeaderFlag(data, len); return rtp_ptr1; } - auto rtp_ptr0 = searchBySSRC(data,len); - if(rtp_ptr0) { + auto rtp_ptr0 = searchBySSRC(data, len); + if (rtp_ptr0) { return rtp_ptr0; } // ssrc搜索失败继续尝试搜索ps header flag - auto rtp_ptr2 = searchByPsHeaderFlag(data,len); + auto rtp_ptr2 = searchByPsHeaderFlag(data, len); return rtp_ptr2; } const char *RtpSession::searchBySSRC(const char *data, size_t len) { InfoL << "尝试rtp搜索ssrc..._ssrc=" << _ssrc; - //搜索第一个rtp的ssrc + // 搜索第一个rtp的ssrc auto ssrc_ptr0 = findSSRC(data, len, _ssrc); if (!ssrc_ptr0) { - //未搜索到任意rtp,返回数据不够 + // 未搜索到任意rtp,返回数据不够 InfoL << "rtp搜索ssrc失败(第一个数据不够),丢弃rtp数据为:" << len; return nullptr; } - //这两个字节是第一个rtp的长度字段 + // 这两个字节是第一个rtp的长度字段 auto rtp_len_ptr = (ssrc_ptr0 - kSSRCOffset); auto rtp_len = ((uint8_t *)rtp_len_ptr)[0] << 8 | ((uint8_t *)rtp_len_ptr)[1]; - //搜索第二个rtp的ssrc - auto ssrc_ptr1 = findSSRC(ssrc_ptr0 + rtp_len, data + (ssize_t) len - ssrc_ptr0 - rtp_len, _ssrc); + // 搜索第二个rtp的ssrc + auto ssrc_ptr1 = findSSRC(ssrc_ptr0 + rtp_len, data + (ssize_t)len - ssrc_ptr0 - rtp_len, _ssrc); if (!ssrc_ptr1) { - //未搜索到第二个rtp,返回数据不够 + // 未搜索到第二个rtp,返回数据不够 InfoL << "rtp搜索ssrc失败(第二个数据不够),丢弃rtp数据为:" << len; return nullptr; } - //两个ssrc的间隔正好等于rtp的长度(外加rtp长度字段),那么说明找到rtp + // 两个ssrc的间隔正好等于rtp的长度(外加rtp长度字段),那么说明找到rtp auto ssrc_offset = ssrc_ptr1 - ssrc_ptr0; if (ssrc_offset == rtp_len + 2 || ssrc_offset == rtp_len + 4) { InfoL << "rtp搜索ssrc成功,tcp上下文恢复成功,丢弃的rtp残余数据为:" << rtp_len_ptr - data; _search_rtp_finished = true; if (rtp_len_ptr == data) { - //停止搜索rtp,否则会进入死循环 + // 停止搜索rtp,否则会进入死循环 _search_rtp = false; } - //前面的数据都需要丢弃,这个是rtp的起始 + // 前面的数据都需要丢弃,这个是rtp的起始 return rtp_len_ptr; } - //第一个rtp长度不匹配,说明第一个找到的ssrc不是rtp,丢弃之,我们从第二个ssrc所在rtp开始搜索 + // 第一个rtp长度不匹配,说明第一个找到的ssrc不是rtp,丢弃之,我们从第二个ssrc所在rtp开始搜索 return ssrc_ptr1 - kSSRCOffset; } const char *RtpSession::searchByPsHeaderFlag(const char *data, size_t len) { - InfoL << "尝试rtp搜索PsSystemHeaderFlag..._ssrc=" << _ssrc; + InfoL << "尝试rtp搜索PsSystemHeaderFlag..._ssrc=" << _ssrc; // 搜索rtp中的第一个PsHeaderFlag - auto ps_header_flag_ptr = findPsHeaderFlag(data,len); + auto ps_header_flag_ptr = findPsHeaderFlag(data, len); if (!ps_header_flag_ptr) { InfoL << "rtp搜索flag失败,丢弃rtp数据为:" << len; return nullptr; } - auto rtp_ptr = ps_header_flag_ptr - kPSHeaderOffset; _search_rtp_finished = true; if (rtp_ptr == data) { - //停止搜索rtp,否则会进入死循环 + // 停止搜索rtp,否则会进入死循环 _search_rtp = false; } InfoL << "rtp搜索flag成功,tcp上下文恢复成功,丢弃的rtp残余数据为:" << rtp_ptr - data; // TODO or Not ? 更新设置ssrc uint32_t rtp_ssrc = 0; - RtpSelector::getSSRC(rtp_ptr+2, len, rtp_ssrc); + RtpSelector::getSSRC(rtp_ptr + 2, len, rtp_ssrc); _ssrc = rtp_ssrc; InfoL << "设置_ssrc为:" << _ssrc; // RtpServer::updateSSRC(uint32_t ssrc) diff --git a/src/Rtp/RtpSession.h b/src/Rtp/RtpSession.h index 0de60db4..5b8d7e1f 100644 --- a/src/Rtp/RtpSession.h +++ b/src/Rtp/RtpSession.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/RtpSplitter.cpp b/src/Rtp/RtpSplitter.cpp index 0f4b6dc4..5a15c923 100644 --- a/src/Rtp/RtpSplitter.cpp +++ b/src/Rtp/RtpSplitter.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/RtpSplitter.h b/src/Rtp/RtpSplitter.h index a2990a7f..216f3021 100644 --- a/src/Rtp/RtpSplitter.h +++ b/src/Rtp/RtpSplitter.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -17,10 +17,6 @@ namespace mediakit{ class RtpSplitter : public HttpRequestSplitter{ -public: - RtpSplitter() = default; - ~RtpSplitter() override = default; - protected: /** * 收到rtp包回调 diff --git a/src/Rtp/TSDecoder.cpp b/src/Rtp/TSDecoder.cpp index 4f00ada0..f3f4086f 100644 --- a/src/Rtp/TSDecoder.cpp +++ b/src/Rtp/TSDecoder.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtp/TSDecoder.h b/src/Rtp/TSDecoder.h index fb306502..849b358b 100644 --- a/src/Rtp/TSDecoder.h +++ b/src/Rtp/TSDecoder.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -25,7 +25,6 @@ class TSSegment : public HttpRequestSplitter { public: typedef std::function onSegment; TSSegment(size_t size = TS_PACKET_SIZE) : _size(size){} - ~TSSegment() = default; void setOnSegment(onSegment cb); static bool isTSPacket(const char *data, size_t len); diff --git a/src/Rtsp/RtpCodec.cpp b/src/Rtsp/RtpCodec.cpp index 6d1d4a9c..65ee311f 100644 --- a/src/Rtsp/RtpCodec.cpp +++ b/src/Rtsp/RtpCodec.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -19,6 +19,7 @@ RtpPacket::Ptr RtpInfo::makeRtp(TrackType type, const void* data, size_t len, bo rtp->setSize(payload_len + RtpPacket::kRtpTcpHeaderSize); rtp->sample_rate = _sample_rate; rtp->type = type; + rtp->track_index = _track_index; //rtsp over tcp 头 auto ptr = (uint8_t *) rtp->data(); diff --git a/src/Rtsp/RtpCodec.h b/src/Rtsp/RtpCodec.h index b1acde58..d63f1962 100644 --- a/src/Rtsp/RtpCodec.h +++ b/src/Rtsp/RtpCodec.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -23,23 +23,14 @@ public: using Ptr = std::shared_ptr; using RingType = toolkit::RingBuffer; - RtpRing() = default; virtual ~RtpRing() = default; - /** - * 获取rtp环形缓存 - * @return - */ - virtual RingType::Ptr getRtpRing() const { - return _ring; - } - /** * 设置rtp环形缓存 * @param ring */ - virtual void setRtpRing(const RingType::Ptr &ring) { - _ring = ring; + void setRtpRing(RingType::Ptr ring) { + _ring = std::move(ring); } /** @@ -63,7 +54,7 @@ class RtpInfo { public: using Ptr = std::shared_ptr; - RtpInfo(uint32_t ssrc, size_t mtu_size, uint32_t sample_rate, uint8_t pt, uint8_t interleaved) { + RtpInfo(uint32_t ssrc, size_t mtu_size, uint32_t sample_rate, uint8_t pt, uint8_t interleaved, int track_index) { if (ssrc == 0) { ssrc = ((uint64_t) this) & 0xFFFFFFFF; } @@ -72,19 +63,14 @@ public: _mtu_size = mtu_size; _sample_rate = sample_rate; _interleaved = interleaved; + _track_index = track_index; } - virtual ~RtpInfo() = default; - //返回rtp负载最大长度 size_t getMaxSize() const { return _mtu_size - RtpPacket::kRtpHeaderSize; } - uint32_t getSsrc() const { - return _ssrc; - } - RtpPacket::Ptr makeRtp(TrackType type,const void *data, size_t len, bool mark, uint64_t stamp); private: @@ -93,20 +79,25 @@ private: uint16_t _seq = 0; uint32_t _ssrc; uint32_t _sample_rate; + int _track_index; size_t _mtu_size; }; -class RtpCodec : public RtpRing, public FrameDispatcher, public CodecInfo { +class RtpCodec : public RtpRing, public FrameDispatcher { public: using Ptr = std::shared_ptr; - RtpCodec() = default; - ~RtpCodec() override = default; + void setRtpInfo(uint32_t ssrc, size_t mtu_size, uint32_t sample_rate, uint8_t pt, uint8_t interleaved = 0, int track_index = 0) { + _rtp_info.reset(new RtpInfo(ssrc, mtu_size, sample_rate, pt, interleaved, track_index)); + } + + RtpInfo &getRtpInfo() { return *_rtp_info; } + +private: + std::unique_ptr _rtp_info; }; }//namespace mediakit - - #endif //ZLMEDIAKIT_RTPCODEC_H diff --git a/src/Rtsp/RtpMultiCaster.cpp b/src/Rtsp/RtpMultiCaster.cpp index e4aaefa1..fefc0f84 100644 --- a/src/Rtsp/RtpMultiCaster.cpp +++ b/src/Rtsp/RtpMultiCaster.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/RtpMultiCaster.h b/src/Rtsp/RtpMultiCaster.h index 98ce46fe..1b9aa1bf 100644 --- a/src/Rtsp/RtpMultiCaster.h +++ b/src/Rtsp/RtpMultiCaster.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -22,7 +22,6 @@ namespace mediakit{ class MultiCastAddressMaker { public: - ~MultiCastAddressMaker() = default; static MultiCastAddressMaker& Instance(); static bool isMultiCastAddress(uint32_t addr); static std::string toString(uint32_t addr); diff --git a/src/Rtsp/RtpReceiver.cpp b/src/Rtsp/RtpReceiver.cpp index 7e669138..8dd88e70 100644 --- a/src/Rtsp/RtpReceiver.cpp +++ b/src/Rtsp/RtpReceiver.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/RtpReceiver.h b/src/Rtsp/RtpReceiver.h index fad10684..c2049855 100644 --- a/src/Rtsp/RtpReceiver.h +++ b/src/Rtsp/RtpReceiver.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -28,8 +28,7 @@ public: static constexpr SEQ SEQ_MAX = (std::numeric_limits::max)(); using iterator = typename std::map::iterator; - PacketSortor() = default; - ~PacketSortor() = default; + virtual ~PacketSortor() = default; void setOnSort(std::function cb) { _cb = std::move(cb); } @@ -201,11 +200,9 @@ public: public: template BadRtpException(Type &&type) : invalid_argument(std::forward(type)) {} - ~BadRtpException() = default; }; RtpTrack(); - virtual ~RtpTrack() = default; void clear(); uint32_t getSSRC() const; @@ -230,9 +227,6 @@ public: using OnSorted = std::function; using BeforeSorted = std::function; - RtpTrackImp() = default; - ~RtpTrackImp() override = default; - void setOnSorted(OnSorted cb); void setBeforeSorted(BeforeSorted cb); diff --git a/src/Rtsp/Rtsp.cpp b/src/Rtsp/Rtsp.cpp index daf09680..331daf15 100644 --- a/src/Rtsp/Rtsp.cpp +++ b/src/Rtsp/Rtsp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/Rtsp.h b/src/Rtsp/Rtsp.h index dc34f918..fde5caea 100644 --- a/src/Rtsp/Rtsp.h +++ b/src/Rtsp/Rtsp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -166,6 +166,8 @@ public: // ntp时间戳 uint64_t ntp_stamp; + int track_index; + static Ptr create(); private: @@ -232,7 +234,6 @@ public: SdpParser() = default; SdpParser(const std::string &sdp) { load(sdp); } - ~SdpParser() = default; void load(const std::string &sdp); bool available() const; @@ -248,7 +249,7 @@ private: /** * rtsp sdp基类 */ -class Sdp : public CodecInfo { +class Sdp { public: using Ptr = std::shared_ptr; @@ -303,8 +304,6 @@ public: std::string getSdp() const override { return _printer; } - CodecId getCodecId() const override { return CodecInvalid; } - float getDuration() const { return _dur_sec; } private: diff --git a/src/Rtsp/RtspDemuxer.cpp b/src/Rtsp/RtspDemuxer.cpp index 10524f90..1dca605b 100644 --- a/src/Rtsp/RtspDemuxer.cpp +++ b/src/Rtsp/RtspDemuxer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -92,7 +92,7 @@ void RtspDemuxer::makeAudioTrack(const SdpTrack::Ptr &audio) { } setBitRate(audio, _audio_track); //生成RtpCodec对象以便解码rtp - _audio_rtp_decoder = Factory::getRtpDecoderByTrack(_audio_track); + _audio_rtp_decoder = Factory::getRtpDecoderByCodecId(_audio_track->getCodecId()); if (!_audio_rtp_decoder) { //找不到相应的rtp解码器,该track无效 _audio_track.reset(); @@ -114,7 +114,7 @@ void RtspDemuxer::makeVideoTrack(const SdpTrack::Ptr &video) { } setBitRate(video, _video_track); //生成RtpCodec对象以便解码rtp - _video_rtp_decoder = Factory::getRtpDecoderByTrack(_video_track); + _video_rtp_decoder = Factory::getRtpDecoderByCodecId(_video_track->getCodecId()); if (!_video_rtp_decoder) { //找不到相应的rtp解码器,该track无效 _video_track.reset(); diff --git a/src/Rtsp/RtspDemuxer.h b/src/Rtsp/RtspDemuxer.h index 51b7bfea..636b6986 100644 --- a/src/Rtsp/RtspDemuxer.h +++ b/src/Rtsp/RtspDemuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,8 +20,6 @@ namespace mediakit { class RtspDemuxer : public Demuxer { public: using Ptr = std::shared_ptr; - RtspDemuxer() = default; - virtual ~RtspDemuxer() = default; /** * 加载sdp diff --git a/src/Rtsp/RtspMediaSource.h b/src/Rtsp/RtspMediaSource.h index bac7fcf9..11253817 100644 --- a/src/Rtsp/RtspMediaSource.h +++ b/src/Rtsp/RtspMediaSource.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/RtspMediaSourceImp.h b/src/Rtsp/RtspMediaSourceImp.h index 483d7610..149bf43a 100644 --- a/src/Rtsp/RtspMediaSourceImp.h +++ b/src/Rtsp/RtspMediaSourceImp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -30,8 +30,6 @@ public: */ RtspMediaSourceImp(const MediaTuple& tuple, int ringSize = RTP_GOP_SIZE); - ~RtspMediaSourceImp() override = default; - /** * 设置sdp */ diff --git a/src/Rtsp/RtspMediaSourceMuxer.h b/src/Rtsp/RtspMediaSourceMuxer.h index 955c6341..1954344f 100644 --- a/src/Rtsp/RtspMediaSourceMuxer.h +++ b/src/Rtsp/RtspMediaSourceMuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/RtspMuxer.cpp b/src/Rtsp/RtspMuxer.cpp index 1665000c..dae5f111 100644 --- a/src/Rtsp/RtspMuxer.cpp +++ b/src/Rtsp/RtspMuxer.cpp @@ -1,43 +1,41 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "RtspMuxer.h" +#include "Common/config.h" #include "Extension/Factory.h" using namespace std; using namespace toolkit; -#define ENABLE_NTP_STAMP 1 - namespace mediakit { void RtspMuxer::onRtp(RtpPacket::Ptr in, bool is_key) { -#if ENABLE_NTP_STAMP if (_live) { - if (_rtp_stamp[in->type] != in->getHeader()->stamp) { - //rtp时间戳变化才计算ntp,节省cpu资源 + auto &ref = _tracks[in->track_index]; + if (ref.rtp_stamp != in->getHeader()->stamp) { + // rtp时间戳变化才计算ntp,节省cpu资源 int64_t stamp_ms = in->getStamp() * uint64_t(1000) / in->sample_rate; int64_t stamp_ms_inc; - //求rtp时间戳增量 - _stamp[in->type].revise(stamp_ms, stamp_ms, stamp_ms_inc, stamp_ms_inc); - _rtp_stamp[in->type] = in->getHeader()->stamp; - _ntp_stamp[in->type] = stamp_ms_inc + _ntp_stamp_start; + // 求rtp时间戳增量 + ref.stamp.revise(stamp_ms, stamp_ms, stamp_ms_inc, stamp_ms_inc); + ref.rtp_stamp = in->getHeader()->stamp; + ref.ntp_stamp = stamp_ms_inc + _ntp_stamp_start; } - //rtp拦截入口,此处统一赋值ntp - in->ntp_stamp = _ntp_stamp[in->type]; + // rtp拦截入口,此处统一赋值ntp + in->ntp_stamp = ref.ntp_stamp; } else { - //点播情况下设置ntp时间戳为rtp时间戳加基准ntp时间戳 + // 点播情况下设置ntp时间戳为rtp时间戳加基准ntp时间戳 in->ntp_stamp = _ntp_stamp_start + (in->getStamp() * uint64_t(1000) / in->sample_rate); } -#endif _rtpRing->write(std::move(in), is_key); } @@ -54,55 +52,95 @@ RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title) { onRtp(std::move(in), is_key); })); -#if ENABLE_NTP_STAMP _ntp_stamp_start = getCurrentMillisecond(true); -#endif } bool RtspMuxer::addTrack(const Track::Ptr &track) { - //根据track生成sdp - Sdp::Ptr sdp = track->getSdp(); - if (!sdp) { + if (_track_existed[track->getTrackType()]) { + // rtsp不支持多个同类型track + WarnL << "Already add a track kind of: " << track->getTrackTypeStr() << ", ignore track: " << track->getCodecName(); return false; } - auto &encoder = _encoder[track->getTrackType()]; - encoder = Factory::getRtpEncoderBySdp(sdp); + auto &ref = _tracks[track->getIndex()]; + auto &encoder = ref.encoder; + CHECK(!encoder); + + // payload type 96以后则为动态pt + Sdp::Ptr sdp = track->getSdp(96 + _index); + if (!sdp) { + WarnL << "Unsupported codec: " << track->getCodecName(); + return false; + } + + encoder = Factory::getRtpEncoderByCodecId(track->getCodecId(), sdp->getPayloadType()); if (!encoder) { return false; } - //设置rtp输出环形缓存 + // 标记已经存在该类型track + _track_existed[track->getTrackType()] = true; + + { + static atomic s_ssrc(0); + uint32_t ssrc = s_ssrc++; + if (!ssrc) { + // ssrc不能为0 + ssrc = s_ssrc++; + } + if (track->getTrackType() == TrackVideo) { + // 视频的ssrc是偶数,方便调试 + ssrc = 2 * ssrc; + } else { + // 音频ssrc是奇数 + ssrc = 2 * ssrc + 1; + } + GET_CONFIG(uint32_t, audio_mtu, Rtp::kAudioMtuSize); + GET_CONFIG(uint32_t, video_mtu, Rtp::kVideoMtuSize); + auto mtu = track->getTrackType() == TrackVideo ? video_mtu : audio_mtu; + encoder->setRtpInfo(ssrc, mtu, sdp->getSampleRate(), sdp->getPayloadType(), 2 * track->getTrackType(), track->getIndex()); + } + + // 设置rtp输出环形缓存 encoder->setRtpRing(_rtpInterceptor); - //添加其sdp - _sdp.append(sdp->getSdp()); + auto str = sdp->getSdp(); + str += "a=control:trackID="; + str += std::to_string(_index); + str += "\r\n"; + + // 添加其sdp + _sdp.append(str); trySyncTrack(); // rtp的时间戳是pts,允许回退 - _stamp[TrackAudio].enableRollback(true); - _stamp[TrackVideo].enableRollback(true); + if (track->getTrackType() == TrackVideo) { + ref.stamp.enableRollback(true); + } + ++_index; return true; } void RtspMuxer::trySyncTrack() { -#if ENABLE_NTP_STAMP - if (_encoder[TrackAudio] && _encoder[TrackVideo]) { - //音频时间戳同步于视频,因为音频时间戳被修改后不影响播放 - _stamp[TrackAudio].syncTo(_stamp[TrackVideo]); + Stamp *first = nullptr; + for (auto &pr : _tracks) { + if (!first) { + first = &pr.second.stamp; + } else { + pr.second.stamp.syncTo(*first); + } } -#endif } bool RtspMuxer::inputFrame(const Frame::Ptr &frame) { - auto &encoder = _encoder[frame->getTrackType()]; + auto &encoder = _tracks[frame->getIndex()].encoder; return encoder ? encoder->inputFrame(frame) : false; } void RtspMuxer::flush() { - for (auto &encoder : _encoder) { - if (encoder) { - encoder->flush(); + for (auto &pr : _tracks) { + if (pr.second.encoder) { + pr.second.encoder->flush(); } } } @@ -117,10 +155,8 @@ RtpRing::RingType::Ptr RtspMuxer::getRtpRing() const { void RtspMuxer::resetTracks() { _sdp.clear(); - for (auto &encoder : _encoder) { - encoder = nullptr; - } + _tracks.clear(); + CLEAR_ARR(_track_existed); } - } /* namespace mediakit */ \ No newline at end of file diff --git a/src/Rtsp/RtspMuxer.h b/src/Rtsp/RtspMuxer.h index 6b5cfa56..00f356e0 100644 --- a/src/Rtsp/RtspMuxer.h +++ b/src/Rtsp/RtspMuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -22,8 +22,6 @@ class RingDelegateHelper : public toolkit::RingDelegate { public: using onRtp = std::function ; - ~RingDelegateHelper() override = default; - RingDelegateHelper(onRtp on_rtp) { _on_rtp = std::move(on_rtp); } @@ -47,7 +45,6 @@ public: * 构造函数 */ RtspMuxer(const TitleSdp::Ptr &title = nullptr); - ~RtspMuxer() override = default; /** * 获取完整的SDP字符串 @@ -88,12 +85,20 @@ private: private: bool _live = true; - uint32_t _rtp_stamp[TrackMax]{0}; - uint64_t _ntp_stamp[TrackMax]{0}; + bool _track_existed[2] = { false, false }; + + uint8_t _index {0}; uint64_t _ntp_stamp_start; std::string _sdp; - Stamp _stamp[TrackMax]; - RtpCodec::Ptr _encoder[TrackMax]; + + struct TrackInfo { + Stamp stamp; + uint32_t rtp_stamp { 0 }; + uint64_t ntp_stamp { 0 }; + RtpCodec::Ptr encoder; + }; + + std::unordered_map _tracks; RtpRing::RingType::Ptr _rtpRing; RtpRing::RingType::Ptr _rtpInterceptor; }; diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index f6a13fda..1cf393e2 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -479,7 +479,7 @@ void RtspPlayer::handleResPAUSE(const Parser &parser, int type) { DebugL << "seekTo(ms):" << iSeekTo; } - onPlayResult_l(SockException(Err_success, type == type_seek ? "resum rtsp success" : "rtsp play success"), !_play_check_timer); + onPlayResult_l(SockException(Err_success, type == type_seek ? "resume rtsp success" : "rtsp play success"), !_play_check_timer); } void RtspPlayer::onWholeRtspPacket(Parser &parser) { diff --git a/src/Rtsp/RtspPlayer.h b/src/Rtsp/RtspPlayer.h index 2b4f34c5..66882c20 100644 --- a/src/Rtsp/RtspPlayer.h +++ b/src/Rtsp/RtspPlayer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/RtspPlayerImp.h b/src/Rtsp/RtspPlayerImp.h index ad0eaa12..6c8818e3 100644 --- a/src/Rtsp/RtspPlayerImp.h +++ b/src/Rtsp/RtspPlayerImp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/RtspPusher.cpp b/src/Rtsp/RtspPusher.cpp index 591b082e..c8531f8d 100644 --- a/src/Rtsp/RtspPusher.cpp +++ b/src/Rtsp/RtspPusher.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/RtspPusher.h b/src/Rtsp/RtspPusher.h index 63353368..d9bfeeea 100644 --- a/src/Rtsp/RtspPusher.h +++ b/src/Rtsp/RtspPusher.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index e25b6f0b..3095b16d 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -57,8 +57,6 @@ RtspSession::RtspSession(const Socket::Ptr &sock) : Session(sock) { sock->setSendTimeOutSecond(keep_alive_sec); } -RtspSession::~RtspSession() = default; - void RtspSession::onError(const SockException &err) { bool is_player = !_push_src_ownership; uint64_t duration = _alive_ticker.createdTime() / 1000; @@ -132,7 +130,9 @@ void RtspSession::onWholeRtspPacket(Parser &parser) { string method = parser.method(); //提取出请求命令字 _cseq = atoi(parser["CSeq"].data()); if (_content_base.empty() && method != "GET") { - _content_base = parser.url(); + RtspUrl rtsp; + rtsp.parse(parser.url()); + _content_base = rtsp._url; _media_info.parse(parser.fullUrl()); _media_info.schema = RTSP_SCHEMA; } @@ -726,17 +726,17 @@ void RtspSession::handleReq_Setup(const Parser &parser) { switch (_rtp_type) { case Rtsp::RTP_TCP: { - if(_push_src){ - //rtsp推流时,interleaved由推流者决定 - auto key_values = Parser::parseArgs(parser["Transport"],";","="); - int interleaved_rtp = -1 , interleaved_rtcp = -1; - if(2 == sscanf(key_values["interleaved"].data(),"%d-%d",&interleaved_rtp,&interleaved_rtcp)){ + if (_push_src) { + // rtsp推流时,interleaved由推流者决定 + auto key_values = Parser::parseArgs(parser["Transport"], ";", "="); + int interleaved_rtp = -1, interleaved_rtcp = -1; + if (2 == sscanf(key_values["interleaved"].data(), "%d-%d", &interleaved_rtp, &interleaved_rtcp)) { trackRef->_interleaved = interleaved_rtp; - }else{ + } else { throw SockException(Err_shutdown, "can not find interleaved when setup of rtp over tcp"); } - }else{ - //rtsp播放时,由于数据共享分发,所以interleaved必须由服务器决定 + } else { + // rtsp播放时,由于数据共享分发,所以interleaved必须由服务器决定 trackRef->_interleaved = 2 * trackRef->_type; } sendRtspResponse("200 OK", diff --git a/src/Rtsp/RtspSession.h b/src/Rtsp/RtspSession.h index ffeb845d..64b8316f 100644 --- a/src/Rtsp/RtspSession.h +++ b/src/Rtsp/RtspSession.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -34,7 +34,6 @@ public: using onAuth = std::function; RtspSession(const toolkit::Socket::Ptr &sock); - virtual ~RtspSession(); ////Session override//// void onRecv(const toolkit::Buffer::Ptr &buf) override; void onError(const toolkit::SockException &err) override; diff --git a/src/Rtsp/RtspSplitter.cpp b/src/Rtsp/RtspSplitter.cpp index f5d1e792..06e9f8c3 100644 --- a/src/Rtsp/RtspSplitter.cpp +++ b/src/Rtsp/RtspSplitter.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -57,13 +57,16 @@ const char *RtspSplitter::onSearchPacketTail_l(const char *data, size_t len) { } ssize_t RtspSplitter::onRecvHeader(const char *data, size_t len) { - if(_isRtpPacket){ - onRtpPacket(data,len); + if (_isRtpPacket) { + onRtpPacket(data, len); + return 0; + } + if (len == 4 && !memcmp(data, "\r\n\r\n", 4)) { return 0; } _parser.parse(data, len); auto ret = getContentLength(_parser); - if(ret == 0){ + if (ret == 0) { onWholeRtspPacket(_parser); _parser.clear(); } diff --git a/src/Rtsp/RtspSplitter.h b/src/Rtsp/RtspSplitter.h index ca9daed2..de268975 100644 --- a/src/Rtsp/RtspSplitter.h +++ b/src/Rtsp/RtspSplitter.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -18,9 +18,6 @@ namespace mediakit{ class RtspSplitter : public HttpRequestSplitter{ public: - RtspSplitter() = default; - virtual ~RtspSplitter() = default; - /** * 是否允许接收rtp包 * @param enable diff --git a/src/Rtsp/UDPServer.cpp b/src/Rtsp/UDPServer.cpp index bb9e4642..23dd4dc7 100644 --- a/src/Rtsp/UDPServer.cpp +++ b/src/Rtsp/UDPServer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Rtsp/UDPServer.h b/src/Rtsp/UDPServer.h index 9ee337db..90f735d4 100644 --- a/src/Rtsp/UDPServer.h +++ b/src/Rtsp/UDPServer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/src/Shell/ShellCMD.h b/src/Shell/ShellCMD.h index 2e283b00..080c4ff1 100644 --- a/src/Shell/ShellCMD.h +++ b/src/Shell/ShellCMD.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -55,8 +55,6 @@ public: (*_parser) << toolkit::Option('s', "stream", toolkit::Option::ArgRequired, nullptr, false, "流id筛选", nullptr); } - virtual ~CMD_media() {} - const char *description() const override { return "媒体源相关操作."; } diff --git a/src/Shell/ShellSession.cpp b/src/Shell/ShellSession.cpp index 85c682ee..8e27c85d 100644 --- a/src/Shell/ShellSession.cpp +++ b/src/Shell/ShellSession.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -28,8 +28,6 @@ ShellSession::ShellSession(const Socket::Ptr &_sock) : Session(_sock) { pleaseInputUser(); } -ShellSession::~ShellSession() = default; - void ShellSession::onRecv(const Buffer::Ptr&buf) { //DebugL << hexdump(buf->data(), buf->size()); GET_CONFIG(uint32_t,maxReqSize,Shell::kMaxReqSize); diff --git a/src/Shell/ShellSession.h b/src/Shell/ShellSession.h index 46113a27..47b2a8fc 100644 --- a/src/Shell/ShellSession.h +++ b/src/Shell/ShellSession.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -20,7 +20,6 @@ namespace mediakit { class ShellSession: public toolkit::Session { public: ShellSession(const toolkit::Socket::Ptr &_sock); - virtual ~ShellSession(); void onRecv(const toolkit::Buffer::Ptr &) override; void onError(const toolkit::SockException &err) override; diff --git a/src/TS/TSMediaSource.h b/src/TS/TSMediaSource.h index b691d15f..5900ec56 100644 --- a/src/TS/TSMediaSource.h +++ b/src/TS/TSMediaSource.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -26,7 +26,6 @@ public: template TSPacket(ARGS && ...args) : BufferOffset(std::forward(args)...) {}; - ~TSPacket() override = default; public: uint64_t time_stamp = 0; diff --git a/src/TS/TSMediaSourceMuxer.h b/src/TS/TSMediaSourceMuxer.h index cdf08fbb..6b8d69ec 100644 --- a/src/TS/TSMediaSourceMuxer.h +++ b/src/TS/TSMediaSourceMuxer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index 9f83ddde..5211fd4c 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -16,8 +16,6 @@ SrtSession::SrtSession(const Socket::Ptr &sock) // TraceL<<"after addr len "<data(); size_t size = buffer->size(); diff --git a/srt/SrtSession.hpp b/srt/SrtSession.hpp index 004a61a1..4064534f 100644 --- a/srt/SrtSession.hpp +++ b/srt/SrtSession.hpp @@ -11,7 +11,6 @@ using namespace toolkit; class SrtSession : public Session { public: SrtSession(const Socket::Ptr &sock); - ~SrtSession() override; void onRecv(const Buffer::Ptr &) override; void onError(const SockException &err) override; diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 56d6bd8a..087bb4ae 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -54,7 +54,7 @@ bool SrtTransportImp::parseStreamid(std::string &streamid) { if (!toolkit::start_with(streamid, "#!::")) { return false; } - _media_info.schema = SRT_SCHEMA; + _media_info.schema = "srt"; std::string real_streamid = streamid.substr(4); std::string vhost, app, stream_name; @@ -287,18 +287,7 @@ std::string SrtTransportImp::getIdentifier() const { bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) { if (_muxer) { - //TraceL<<"before type "<getCodecName()<<" dts "<dts()<<" pts "<pts(); - auto frame_tmp = std::make_shared(frame, _type_to_stamp[frame->getTrackType()],false); - if(_type_to_stamp.size()>1){ - // 有音视频,检查是否时间戳是否差距过大 - auto diff = _type_to_stamp[TrackType::TrackVideo].getRelativeStamp() - _type_to_stamp[TrackType::TrackAudio].getRelativeStamp(); - if(std::abs(diff) > 5000){ - // 超过5s,应该同步 TODO - WarnL << _media_info.full_url <<" video or audio not sync : "<getCodecName()<<" dts "<dts()<<" pts "<pts(); - return _muxer->inputFrame(frame_tmp); + return _muxer->inputFrame(frame); } if (_cached_func.size() > 200) { WarnL << "cached frame of track(" << frame->getCodecName() << ") is too much, now dropped"; @@ -306,17 +295,11 @@ bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) { } auto frame_cached = Frame::getCacheAbleFrame(frame); lock_guard lck(_func_mtx); - _cached_func.emplace_back([this, frame_cached]() { - //TraceL<<"before type "<getCodecName()<<" dts "<dts()<<" pts "<pts(); - auto frame_tmp = std::make_shared(frame_cached, _type_to_stamp[frame_cached->getTrackType()],false); - //TraceL<<"after type "<getCodecName()<<" dts "<dts()<<" pts "<pts(); - _muxer->inputFrame(frame_tmp); - }); + _cached_func.emplace_back([this, frame_cached]() { _muxer->inputFrame(frame_cached); }); return true; } bool SrtTransportImp::addTrack(const Track::Ptr &track) { - _type_to_stamp.emplace(track->getTrackType(),Stamp()); if (_muxer) { return _muxer->addTrack(track); } @@ -333,9 +316,6 @@ void SrtTransportImp::addTrackCompleted() { lock_guard lck(_func_mtx); _cached_func.emplace_back([this]() { _muxer->addTrackCompleted(); }); } - if(_type_to_stamp.size() >1){ - _type_to_stamp[TrackType::TrackAudio].syncTo(_type_to_stamp[TrackType::TrackVideo]); - } } void SrtTransportImp::doCachedFunc() { diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index 71478605..9c1ac47e 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -86,8 +86,6 @@ private: DecoderImp::Ptr _decoder; std::recursive_mutex _func_mtx; std::deque> _cached_func; - - std::unordered_map _type_to_stamp; }; } // namespace SRT diff --git a/tests/DeviceHK/DeviceHK.cpp b/tests/DeviceHK/DeviceHK.cpp index 44cf5dd9..0aa51513 100644 --- a/tests/DeviceHK/DeviceHK.cpp +++ b/tests/DeviceHK/DeviceHK.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/DeviceHK/DeviceHK.h b/tests/DeviceHK/DeviceHK.h index 68ea1aa0..103e4262 100644 --- a/tests/DeviceHK/DeviceHK.h +++ b/tests/DeviceHK/DeviceHK.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/bom.cpp b/tests/bom.cpp index 8c778787..eb6ee6f6 100644 --- a/tests/bom.cpp +++ b/tests/bom.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/tab.cpp b/tests/tab.cpp index e937330e..49fb19c3 100644 --- a/tests/tab.cpp +++ b/tests/tab.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_bench_forward.cpp b/tests/test_bench_forward.cpp index 634d7b8e..eb6df202 100644 --- a/tests/test_bench_forward.cpp +++ b/tests/test_bench_forward.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -138,7 +138,7 @@ int main(int argc, char *argv[]) { auto parse_urls = [&]() { // 获取输入源列表 - auto inputs = ::split(toolkit::File::loadFile(in_urls.c_str()), "\n"); + auto inputs = ::split(toolkit::File::loadFile(in_urls), "\n"); for(auto &url : inputs){ if(url.empty() || url.find("://") == std::string::npos) { continue; @@ -147,7 +147,7 @@ int main(int argc, char *argv[]) { input_urls.emplace_back(input_url); } // 获取输出源列表 - auto outputs = ::split(toolkit::File::loadFile(out_urls.c_str()), "\n"); + auto outputs = ::split(toolkit::File::loadFile(out_urls), "\n"); for(auto &url : outputs){ if(url.empty() || url.find("://") == std::string::npos){ continue; diff --git a/tests/test_bench_pull.cpp b/tests/test_bench_pull.cpp index 321ae542..c16de46a 100644 --- a/tests/test_bench_pull.cpp +++ b/tests/test_bench_pull.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_bench_push.cpp b/tests/test_bench_push.cpp index b34f8b99..604ad76f 100644 --- a/tests/test_bench_push.cpp +++ b/tests/test_bench_push.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_flv.cpp b/tests/test_flv.cpp index ffed816f..49b78865 100644 --- a/tests/test_flv.cpp +++ b/tests/test_flv.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_httpApi.cpp b/tests/test_httpApi.cpp index 081311db..5fd1ea4a 100644 --- a/tests/test_httpApi.cpp +++ b/tests/test_httpApi.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_httpClient.cpp b/tests/test_httpClient.cpp index 9c581a1c..4040b22d 100644 --- a/tests/test_httpClient.cpp +++ b/tests/test_httpClient.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_pusher.cpp b/tests/test_pusher.cpp index 8e5ca1f7..025cdd0f 100644 --- a/tests/test_pusher.cpp +++ b/tests/test_pusher.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_pusherMp4.cpp b/tests/test_pusherMp4.cpp index 51298899..41e91dea 100644 --- a/tests/test_pusherMp4.cpp +++ b/tests/test_pusherMp4.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_rtcp_nack.cpp b/tests/test_rtcp_nack.cpp index 864c3b2f..642ca123 100644 --- a/tests/test_rtcp_nack.cpp +++ b/tests/test_rtcp_nack.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLToolKit project authors. All Rights Reserved. * * This file is part of ZLToolKit(https://github.com/xia-chu/ZLToolKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_rtp.cpp b/tests/test_rtp.cpp index d68785df..5bdffa12 100644 --- a/tests/test_rtp.cpp +++ b/tests/test_rtp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_server.cpp b/tests/test_server.cpp index dc123ba2..d94ccbeb 100644 --- a/tests/test_server.cpp +++ b/tests/test_server.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_sortor.cpp b/tests/test_sortor.cpp index 7968a2c9..0d29dfbd 100644 --- a/tests/test_sortor.cpp +++ b/tests/test_sortor.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_wsClient.cpp b/tests/test_wsClient.cpp index a3819799..d240bce3 100644 --- a/tests/test_wsClient.cpp +++ b/tests/test_wsClient.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tests/test_wsServer.cpp b/tests/test_wsServer.cpp index f839d352..2f4d8493 100644 --- a/tests/test_wsServer.cpp +++ b/tests/test_wsServer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/tools/openapi/generates.py b/tools/openapi/generates.py index 2fdc1d32..77965ebd 100644 --- a/tools/openapi/generates.py +++ b/tools/openapi/generates.py @@ -43,18 +43,26 @@ def run_cmd(cmd: str, assert_success=False, capture_output=False, env=None) -> b return True -def check_dependencies() -> None: +def check_dependencies(need_install:bool = False) -> None: """ check dependencies :return: """ if not check_installed("p2o"): - print() - print("p2o is not installed, please install it first!") - print("If you use npm, you can install it by the following command:") - print("npm install -g postman-to-openapi") - print() - sys.exit(1) + if not need_install: + print() + print("p2o is not installed, please install it first!") + print("If you use npm, you can install it by the following command:") + print("npm install -g postman-to-openapi") + print() + sys.exit(1) + else: + # 先检查是否安装了npm, 没有就自动安装 + if not check_installed("npm"): + print("npm is not installed, install it first") + run_cmd("sudo apt install npm -y") + print("p2o is not installed, install it") + run_cmd("sudo npm install -g postman-to-openapi") else: print("p2o is installed") @@ -70,6 +78,12 @@ def get_version() -> str: elif os.path.isfile("../../cmake-build-release/version.h"): print("Found version.h in cmake-build-release") version_h_path = "../../cmake-build-release/version.h" + elif os.path.isfile("../../build/version.h"): + print("Found version.h in build") + version_h_path = "../../build/version.h" + elif os.path.isfile("../../linux_build/version.h"): + print("Found version.h in linux_build") + version_h_path = "../../linux_build/version.h" else: print("version.h not found") print("Please compile first") @@ -138,7 +152,11 @@ def generate() -> None: if __name__ == "__main__": - check_dependencies() + # 如果有参数install-dependencies,则安装依赖 + if len(sys.argv) > 1 and sys.argv[1] == "install-dependencies": + check_dependencies(True) + else: + check_dependencies() version = get_version() secret = get_secret() update_options(version, secret) diff --git a/webrtc/Nack.cpp b/webrtc/Nack.cpp index a12bfa7e..6197117e 100644 --- a/webrtc/Nack.cpp +++ b/webrtc/Nack.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/webrtc/Nack.h b/webrtc/Nack.h index 8780e27a..b0cd22b4 100644 --- a/webrtc/Nack.h +++ b/webrtc/Nack.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -22,9 +22,6 @@ namespace mediakit { class NackList { public: - NackList() = default; - ~NackList() = default; - void pushBack(RtpPacket::Ptr rtp); void forEach(const FCI_NACK &nack, const std::function &cb); @@ -58,7 +55,6 @@ public: static_assert(kNackRtpSize >=0 && kNackRtpSize <= FCI_NACK::kBitSize, "NackContext::kNackRtpSize must between 0 and 16"); NackContext(); - ~NackContext() = default; void received(uint16_t seq, bool is_rtx = false); void setOnNack(onNack cb); diff --git a/webrtc/RtpExt.cpp b/webrtc/RtpExt.cpp index b7d97b5c..d1ade570 100644 --- a/webrtc/RtpExt.cpp +++ b/webrtc/RtpExt.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/webrtc/RtpExt.h b/webrtc/RtpExt.h index 524fa3bb..a7aea281 100644 --- a/webrtc/RtpExt.h +++ b/webrtc/RtpExt.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -53,7 +53,6 @@ public: template friend void appendExt(std::map &ret, uint8_t *ptr, const uint8_t *end); friend class RtpExtContext; - ~RtpExt() = default; static std::map getExtValue(const RtpHeader *header); static RtpExtType getExtType(const std::string &url); @@ -119,7 +118,6 @@ public: using OnGetRtp = std::function; RtpExtContext(const RtcMedia &media); - ~RtpExtContext() = default; void setOnGetRtp(OnGetRtp cb); std::string getRid(uint32_t ssrc) const; diff --git a/webrtc/Sdp.cpp b/webrtc/Sdp.cpp index 7051e42f..bed1bf57 100644 --- a/webrtc/Sdp.cpp +++ b/webrtc/Sdp.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -267,16 +267,23 @@ void RtcSessionSdp::parse(const string &str) { static auto flag = registerAllItem(); RtcSdpBase *media = nullptr; auto lines = split(str, "\n"); - for(auto &line : lines){ + std::set line_set; + for (auto &line : lines) { trim(line); - if(line.size() < 3 || line[1] != '='){ + if (line.size() < 3 || line[1] != '=') { continue; } + + if (!line_set.emplace(line).second) { + continue; + } + auto key = line.substr(0, 1); auto value = line.substr(2); if (!strcasecmp(key.data(), "m")) { medias.emplace_back(RtcSdpBase()); media = &medias.back(); + line_set.clear(); } SdpItem::Ptr item; diff --git a/webrtc/Sdp.h b/webrtc/Sdp.h index a96774c1..cec182a8 100644 --- a/webrtc/Sdp.h +++ b/webrtc/Sdp.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/webrtc/TwccContext.cpp b/webrtc/TwccContext.cpp index bbdba654..61fa4388 100644 --- a/webrtc/TwccContext.cpp +++ b/webrtc/TwccContext.cpp @@ -1,9 +1,9 @@ /* * Copyright (c) 2021 The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/webrtc/TwccContext.h b/webrtc/TwccContext.h index db81edc6..91485bdf 100644 --- a/webrtc/TwccContext.h +++ b/webrtc/TwccContext.h @@ -1,9 +1,9 @@ /* * Copyright (c) 2021 The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -26,9 +26,6 @@ public: //每个twcc rtcp包发送的最大时间间隔,单位毫秒 static constexpr size_t kMaxTimeDelta = 256; - TwccContext() = default; - ~TwccContext() = default; - void onRtp(uint32_t ssrc, uint16_t twcc_ext_seq, uint64_t stamp_ms); void setOnSendTwccCB(onSendTwccCB cb); diff --git a/webrtc/WebRtcEchoTest.cpp b/webrtc/WebRtcEchoTest.cpp index f55ea198..40be2613 100644 --- a/webrtc/WebRtcEchoTest.cpp +++ b/webrtc/WebRtcEchoTest.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/webrtc/WebRtcEchoTest.h b/webrtc/WebRtcEchoTest.h index 0ab74e7b..397406c1 100644 --- a/webrtc/WebRtcEchoTest.h +++ b/webrtc/WebRtcEchoTest.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -18,7 +18,6 @@ namespace mediakit { class WebRtcEchoTest : public WebRtcTransportImp { public: using Ptr = std::shared_ptr; - ~WebRtcEchoTest() override = default; static Ptr create(const EventPoller::Ptr &poller); protected: diff --git a/webrtc/WebRtcPlayer.cpp b/webrtc/WebRtcPlayer.cpp index 63f174eb..bdc82697 100644 --- a/webrtc/WebRtcPlayer.cpp +++ b/webrtc/WebRtcPlayer.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/webrtc/WebRtcPlayer.h b/webrtc/WebRtcPlayer.h index 02208f6d..8daa7f8b 100644 --- a/webrtc/WebRtcPlayer.h +++ b/webrtc/WebRtcPlayer.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -19,7 +19,6 @@ namespace mediakit { class WebRtcPlayer : public WebRtcTransportImp { public: using Ptr = std::shared_ptr; - ~WebRtcPlayer() override = default; static Ptr create(const EventPoller::Ptr &poller, const RtspMediaSource::Ptr &src, const MediaInfo &info, bool preferred_tcp = false); MediaInfo getMediaInfo() { return _media_info; } diff --git a/webrtc/WebRtcPusher.cpp b/webrtc/WebRtcPusher.cpp index 92b4ad04..47df47c9 100644 --- a/webrtc/WebRtcPusher.cpp +++ b/webrtc/WebRtcPusher.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ diff --git a/webrtc/WebRtcPusher.h b/webrtc/WebRtcPusher.h index 8d309395..bd4775e2 100644 --- a/webrtc/WebRtcPusher.h +++ b/webrtc/WebRtcPusher.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -19,7 +19,6 @@ namespace mediakit { class WebRtcPusher : public WebRtcTransportImp, public MediaSourceEvent { public: using Ptr = std::shared_ptr; - ~WebRtcPusher() override = default; static Ptr create(const EventPoller::Ptr &poller, const RtspMediaSource::Ptr &src, const std::shared_ptr &ownership, const MediaInfo &info, const ProtocolOption &option, bool preferred_tcp = false); diff --git a/webrtc/WebRtcSession.cpp b/webrtc/WebRtcSession.cpp index ee3051c0..ff76dbee 100644 --- a/webrtc/WebRtcSession.cpp +++ b/webrtc/WebRtcSession.cpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -51,8 +51,6 @@ WebRtcSession::WebRtcSession(const Socket::Ptr &sock) : Session(sock) { _over_tcp = sock->sockType() == SockNum::Sock_TCP; } -WebRtcSession::~WebRtcSession() = default; - void WebRtcSession::attachServer(const Server &server) { _server = std::static_pointer_cast(const_cast(server).shared_from_this()); } diff --git a/webrtc/WebRtcSession.h b/webrtc/WebRtcSession.h index 9cf7343c..3bfd96bc 100644 --- a/webrtc/WebRtcSession.h +++ b/webrtc/WebRtcSession.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -27,7 +27,6 @@ using namespace toolkit; class WebRtcSession : public Session, public HttpRequestSplitter { public: WebRtcSession(const Socket::Ptr &sock); - ~WebRtcSession() override; void attachServer(const Server &server) override; void onRecv(const Buffer::Ptr &) override; diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index 3f798358..685e9f89 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -1,15 +1,17 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include #include +#include "Util/base64.h" +#include "Network/sockutil.h" #include "Common/config.h" #include "RtpExt.h" #include "Rtcp/Rtcp.h" @@ -22,7 +24,6 @@ #include "WebRtcEchoTest.h" #include "WebRtcPlayer.h" #include "WebRtcPusher.h" - #include "Rtsp/RtspMediaSourceImp.h" #define RTP_SSRC_OFFSET 1 @@ -47,15 +48,23 @@ const string kExternIP = RTC_FIELD "externIP"; const string kRembBitRate = RTC_FIELD "rembBitRate"; // webrtc单端口udp服务器 const string kPort = RTC_FIELD "port"; - const string kTcpPort = RTC_FIELD "tcpPort"; +// 比特率设置 +const string kStartBitrate = RTC_FIELD "start_bitrate"; +const string kMaxBitrate = RTC_FIELD "max_bitrate"; +const string kMinBitrate = RTC_FIELD "min_bitrate"; + static onceToken token([]() { mINI::Instance()[kTimeOutSec] = 15; mINI::Instance()[kExternIP] = ""; mINI::Instance()[kRembBitRate] = 0; mINI::Instance()[kPort] = 0; mINI::Instance()[kTcpPort] = 0; + + mINI::Instance()[kStartBitrate] = 0; + mINI::Instance()[kMaxBitrate] = 0; + mINI::Instance()[kMinBitrate] = 0; }); } // namespace RTC @@ -77,6 +86,28 @@ static void translateIPFromEnv(std::vector &v) { } } +static std::string getServerPrefix() { + //stun_user_name格式: base64(ip+udp_port+tcp_port) + _ + number + //其中ip为二进制char[4], udp_port/tcp_port为大端 uint16. + //number为自增长数,确保短时间内唯一 + GET_CONFIG(uint16_t, udp_port, Rtc::kPort); + GET_CONFIG(uint16_t, tcp_port, Rtc::kTcpPort); + char buf[8]; + auto host = SockUtil::get_local_ip(); + auto addr = SockUtil::make_sockaddr(host.data(), udp_port); + //拷贝ipv4地址 + memcpy(buf, &(reinterpret_cast(&addr)->sin_addr), 4); + //拷贝udp端口 + memcpy(buf + 4, &(reinterpret_cast(&addr)->sin_port), 2); + //tcp端口转大端模式 + addr = SockUtil::make_sockaddr(host.data(), tcp_port); + //拷贝tcp端口 + memcpy(buf + 6, &(reinterpret_cast(&addr)->sin_port), 2); + auto ret = encodeBase64(string(buf, 8)) + '_'; + InfoL << "MediaServer(" << host << ":" << udp_port << ":" << tcp_port << ") prefix: " << ret; + return ret; +} + const char* sockTypeStr(Session* session) { if (session) { switch (session->getSock()->sockType()) { @@ -90,7 +121,8 @@ const char* sockTypeStr(Session* session) { WebRtcTransport::WebRtcTransport(const EventPoller::Ptr &poller) { _poller = poller; - _identifier = "zlm" + to_string(++s_key); + static auto prefix = getServerPrefix(); + _identifier = prefix + to_string(++s_key); _packet_pool.setSize(64); } @@ -295,6 +327,20 @@ void WebRtcTransport::onRtcConfigure(RtcConfigure &configure) const { configure.enableTWCC(!remb_bit_rate); } +static void setSdpBitrate(RtcSession &sdp) { + GET_CONFIG(size_t, max_bitrate, Rtc::kMaxBitrate); + GET_CONFIG(size_t, min_bitrate, Rtc::kMinBitrate); + GET_CONFIG(size_t, start_bitrate, Rtc::kStartBitrate); + + auto m = (RtcMedia *)(sdp.getMedia(TrackType::TrackVideo)); + if (m) { + auto &plan = m->plan[0]; + if (max_bitrate) plan.fmtp["x-google-max-bitrate"] = std::to_string(max_bitrate); + if (min_bitrate) plan.fmtp["x-google-min-bitrate"] = std::to_string(min_bitrate); + if (start_bitrate) plan.fmtp["x-google-start-bitrate"] = std::to_string(start_bitrate); + } +} + std::string WebRtcTransport::getAnswerSdp(const string &offer) { try { //// 解析offer sdp //// @@ -316,6 +362,7 @@ std::string WebRtcTransport::getAnswerSdp(const string &offer) { //// 生成answer sdp //// _answer_sdp = configure.createAnswer(*_offer_sdp); onCheckSdp(SdpType::answer, *_answer_sdp); + setSdpBitrate(*_answer_sdp); _answer_sdp->checkValid(); return _answer_sdp->toString(); } catch (exception &ex) { @@ -636,7 +683,7 @@ makeIceCandidate(std::string ip, uint16_t port, uint32_t priority = 100, std::st candidate->foundation = proto + "candidate"; // 优先级,单candidate时随便 candidate->priority = priority; - candidate->address = ip; + candidate->address = std::move(ip); candidate->port = port; candidate->type = "host"; if (proto == "tcp") { @@ -647,6 +694,12 @@ makeIceCandidate(std::string ip, uint16_t port, uint32_t priority = 100, std::st void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const { WebRtcTransport::onRtcConfigure(configure); + if (!_cands.empty()) { + for (auto &cand : _cands) { + configure.addCandidate(cand); + } + return; + } GET_CONFIG(uint16_t, local_udp_port, Rtc::kPort); GET_CONFIG(uint16_t, local_tcp_port, Rtc::kTcpPort); @@ -674,6 +727,10 @@ void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const { } } +void WebRtcTransportImp::setIceCandidate(vector cands) { + _cands = std::move(cands); +} + /////////////////////////////////////////////////////////////////// class RtpChannel : public RtpTrackImp, public std::enable_shared_from_this { @@ -687,8 +744,6 @@ public: _nack_ctx.setOnNack([this](const FCI_NACK &nack) { onNack(nack); }); } - ~RtpChannel() override = default; - RtpPacket::Ptr inputRtp(TrackType type, int sample_rate, uint8_t *ptr, size_t len, bool is_rtx) { auto rtp = RtpTrack::inputRtp(type, sample_rate, ptr, len); if (!rtp) { @@ -786,7 +841,6 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) { if (!rtp_chn) { WarnL << "未识别的sr rtcp包:" << rtcp->dumpString(); } else { - // InfoL << "接收丢包率,ssrc:" << sr->ssrc << ",loss rate(%):" << rtp_chn->getLossRate(); // 设置rtp时间戳与ntp时间戳的对应关系 rtp_chn->setNtpStamp(sr->rtpts, sr->getNtpUnixStampMS()); auto rr = rtp_chn->createRtcpRR(sr, track->answer_ssrc_rtp); @@ -1168,8 +1222,26 @@ std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& off return const_cast(exchanger).getAnswerSdp(offer); } -void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, const WebRtcArgs &args, const onCreateRtc &cb) { +void WebRtcPluginManager::setListener(Listener cb) { lock_guard lck(_mtx_creator); + _listener = std::move(cb); +} + +void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, const WebRtcArgs &args, const onCreateRtc &cb_in) { + onCreateRtc cb; + lock_guard lck(_mtx_creator); + if (_listener) { + auto listener = _listener; + auto args_ptr = args.shared_from_this(); + auto sender_ptr = static_pointer_cast(sender.shared_from_this()); + cb = [listener, sender_ptr, type, args_ptr, cb_in](const WebRtcInterface &rtc) { + listener(*sender_ptr, type, *args_ptr, rtc); + cb_in(rtc); + }; + } else { + cb = cb_in; + } + auto it = _map_creator.find(type); if (it == _map_creator.end()) { cb(WebRtcException(SockException(Err_other, "the type can not supported"))); @@ -1258,7 +1330,7 @@ void play_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana return; } // 还原成rtc,目的是为了hook时识别哪种播放协议 - info.schema = RTC_SCHEMA; + info.schema = "rtc"; auto rtc = WebRtcPlayer::create(EventPollerPool::Instance().getPoller(), src, info, preferred_tcp); cb(*rtc); }); @@ -1272,10 +1344,40 @@ void play_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana } } +static void set_webrtc_cands(const WebRtcArgs &args, const WebRtcInterface &rtc) { + vector cands; + { + auto cand_str = trim(args["cand_udp"]); + auto ip_port = toolkit::split(cand_str, ":"); + if (ip_port.size() == 2) { + // udp优先 + auto ice_cand = makeIceCandidate(ip_port[0], atoi(ip_port[1].data()), 120, "udp"); + cands.emplace_back(std::move(*ice_cand)); + } + } + { + auto cand_str = trim(args["cand_tcp"]); + auto ip_port = toolkit::split(cand_str, ":"); + if (ip_port.size() == 2) { + // tcp模式 + auto ice_cand = makeIceCandidate(ip_port[0], atoi(ip_port[1].data()), 100, "tcp"); + cands.emplace_back(std::move(*ice_cand)); + } + } + if (!cands.empty()) { + // udp优先 + const_cast(rtc).setIceCandidate(std::move(cands)); + } +} + static onceToken s_rtc_auto_register([]() { WebRtcPluginManager::Instance().registerPlugin("echo", echo_plugin); WebRtcPluginManager::Instance().registerPlugin("push", push_plugin); WebRtcPluginManager::Instance().registerPlugin("play", play_plugin); + + WebRtcPluginManager::Instance().setListener([](Session &sender, const std::string &type, const WebRtcArgs &args, const WebRtcInterface &rtc) { + set_webrtc_cands(args, rtc); + }); }); }// namespace mediakit \ No newline at end of file diff --git a/webrtc/WebRtcTransport.h b/webrtc/WebRtcTransport.h index 2d1e6bbf..d0e1d67c 100644 --- a/webrtc/WebRtcTransport.h +++ b/webrtc/WebRtcTransport.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * - * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * - * Use of this source code is governed by MIT license that can be found in the + * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ @@ -37,11 +37,11 @@ extern const std::string kTimeOutSec; class WebRtcInterface { public: - WebRtcInterface() = default; virtual ~WebRtcInterface() = default; virtual std::string getAnswerSdp(const std::string &offer) = 0; virtual const std::string& getIdentifier() const = 0; virtual const std::string& deleteRandStr() const { static std::string s_null; return s_null; } + virtual void setIceCandidate(std::vector cands) {} }; std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& offer); @@ -49,7 +49,6 @@ std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& off class WebRtcException : public WebRtcInterface { public: WebRtcException(const SockException &ex) : _ex(ex) {}; - ~WebRtcException() override = default; std::string getAnswerSdp(const std::string &offer) override { throw _ex; } @@ -70,7 +69,6 @@ class WebRtcTransport : public WebRtcInterface, public RTC::DtlsTransport::Liste public: using Ptr = std::shared_ptr; WebRtcTransport(const EventPoller::Ptr &poller); - ~WebRtcTransport() override = default; /** * 创建对象 @@ -251,6 +249,7 @@ public: void onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool rtx = false); void createRtpChannel(const std::string &rid, uint32_t ssrc, MediaTrack &track); + void setIceCandidate(std::vector cands) override; void removeTuple(RTC::TransportTuple* tuple); void safeShutdown(const SockException &ex); @@ -306,6 +305,7 @@ private: std::unordered_map _ssrc_to_track; //根据接收rtp的pt获取相关信息 std::unordered_map> _pt_to_track; + std::vector _cands; }; class WebRtcTransportManager { @@ -324,9 +324,8 @@ private: std::unordered_map > _map; }; -class WebRtcArgs { +class WebRtcArgs : public std::enable_shared_from_this { public: - WebRtcArgs() = default; virtual ~WebRtcArgs() = default; virtual variant operator[](const std::string &key) const = 0; @@ -336,17 +335,20 @@ class WebRtcPluginManager { public: using onCreateRtc = std::function; using Plugin = std::function; + using Listener = std::function; static WebRtcPluginManager &Instance(); void registerPlugin(const std::string &type, Plugin cb); void getAnswerSdp(Session &sender, const std::string &type, const WebRtcArgs &args, const onCreateRtc &cb); + void setListener(Listener cb); private: WebRtcPluginManager() = default; private: mutable std::mutex _mtx_creator; + Listener _listener; std::unordered_map _map_creator; }; diff --git a/www/readme/index.html b/www/readme/index.html index 32a9e712..5adb4a6d 100644 --- a/www/readme/index.html +++ b/www/readme/index.html @@ -1,7 +1,7 @@ 欢迎使用ZLMediaKit -

    欢迎使用ZLMediaKit,请阅读wiki 获取更多帮助!

    +

    欢迎使用ZLMediaKit,请阅读wiki 获取更多帮助!


    ZLMediaKit
    diff --git a/www/swagger/openapi.json b/www/swagger/openapi.json index 485cfe9e..480c977c 100644 --- a/www/swagger/openapi.json +++ b/www/swagger/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "ZLMediaKit HTTP API", "description": "You can test the HTTP API provided by ZlMediaKit here. For usage documentation, please refer to [here](https://docs.zlmediakit.com/guide/media_server/restful_api.html)", - "version": "ZLMediaKit(git hash:\"a78ca2e\"/\"2023-11-17T11:12:51+08:00\",branch:\"patch-63\",build time:\"2023-11-23T14:35:02\")", + "version": "ZLMediaKit(git hash:\"5028151\"/\"2023-12-01T14:43:35+08:00\",branch:\"master\",build time:\"2023-12-01T07:54:14\")", "x-logo": { "url": "/logo.png", "backgroundColor": "#FFFFFF", @@ -45,7 +45,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -70,7 +70,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -97,7 +97,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -122,7 +122,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -149,7 +149,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -174,7 +174,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -201,7 +201,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -226,7 +226,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -253,7 +253,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -278,7 +278,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -305,7 +305,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "api.apiDebug", @@ -339,7 +339,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "api.apiDebug", @@ -375,7 +375,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -400,7 +400,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -427,7 +427,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -452,7 +452,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -479,7 +479,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -540,7 +540,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -603,7 +603,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -664,7 +664,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -727,7 +727,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -752,7 +752,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -779,7 +779,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "id", @@ -813,7 +813,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "id", @@ -849,7 +849,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -874,7 +874,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -901,7 +901,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -962,7 +962,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -1025,7 +1025,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -1059,7 +1059,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -1095,7 +1095,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1165,7 +1165,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1237,7 +1237,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -1271,7 +1271,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -1307,7 +1307,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "src_url", @@ -1377,7 +1377,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "src_url", @@ -1449,7 +1449,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -1482,7 +1482,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -1517,7 +1517,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1578,7 +1578,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1641,7 +1641,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1702,7 +1702,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1765,7 +1765,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1834,7 +1834,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1905,7 +1905,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -1966,7 +1966,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "schema", @@ -2029,7 +2029,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -2099,7 +2099,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -2171,7 +2171,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -2232,7 +2232,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -2295,7 +2295,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "type", @@ -2356,7 +2356,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "type", @@ -2419,7 +2419,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -2480,7 +2480,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -2543,7 +2543,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -2604,7 +2604,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -2667,7 +2667,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "type", @@ -2728,7 +2728,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "type", @@ -2791,7 +2791,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "type", @@ -2852,7 +2852,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "type", @@ -2915,7 +2915,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "url", @@ -2967,7 +2967,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "url", @@ -3021,7 +3021,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3055,7 +3055,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3091,7 +3091,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "port", @@ -3143,7 +3143,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "port", @@ -3197,7 +3197,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "dst_url", @@ -3249,7 +3249,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "dst_url", @@ -3303,7 +3303,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3337,7 +3337,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3373,7 +3373,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3416,7 +3416,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3461,7 +3461,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3495,7 +3495,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3531,7 +3531,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3565,7 +3565,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "stream_id", @@ -3601,7 +3601,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -3626,7 +3626,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -3653,7 +3653,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -3741,7 +3741,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -3831,7 +3831,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -3892,7 +3892,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -3955,7 +3955,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -4007,7 +4007,7 @@ "type": "string" }, "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "vhost", @@ -4060,7 +4060,7 @@ "schema": { "type": "string" }, - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -4084,7 +4084,7 @@ "schema": { "type": "string" }, - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" } ], "responses": { @@ -4110,7 +4110,7 @@ "schema": { "type": "string" }, - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -4142,7 +4142,7 @@ "schema": { "type": "string" }, - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -4176,7 +4176,7 @@ "schema": { "type": "string" }, - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -4208,7 +4208,7 @@ "schema": { "type": "string" }, - "example": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX" + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" }, { "name": "key", @@ -4228,6 +4228,130 @@ } } } + }, + "/index/api/loadMP4File": { + "get": { + "tags": [ + "GET" + ], + "summary": "\u70b9\u64admp4\u6587\u4ef6(loadMP4File)", + "parameters": [ + { + "name": "secret", + "in": "query", + "schema": { + "type": "string" + }, + "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" + }, + { + "name": "vhost", + "in": "query", + "schema": { + "type": "string" + }, + "description": "\u6dfb\u52a0\u7684\u6d41\u7684\u865a\u62df\u4e3b\u673a\uff0c\u4f8b\u5982__defaultVhost__", + "example": "__defaultVhost__" + }, + { + "name": "app", + "in": "query", + "schema": { + "type": "string" + }, + "description": "\u6dfb\u52a0\u7684\u6d41\u7684\u5e94\u7528\u540d\uff0c\u4f8b\u5982live", + "example": "live" + }, + { + "name": "stream", + "in": "query", + "schema": { + "type": "string" + }, + "description": "\u6dfb\u52a0\u7684\u6d41\u7684id\u540d\uff0c\u4f8b\u5982test", + "example": "test" + }, + { + "name": "file_path", + "in": "query", + "schema": { + "type": "string" + }, + "description": "mp4\u6587\u4ef6\u7edd\u5bf9\u8def\u5f84", + "example": "/path/to/mp4/file.mp4" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": {} + } + } + } + }, + "post": { + "tags": [ + "POST" + ], + "summary": "\u70b9\u64admp4\u6587\u4ef6(loadMP4File)", + "parameters": [ + { + "name": "secret", + "in": "query", + "schema": { + "type": "string" + }, + "description": "api\u64cd\u4f5c\u5bc6\u94a5(\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e)", + "example": "FTRaFEWs08KeTxKEEO25ePDKuV3CjOqp" + }, + { + "name": "vhost", + "in": "query", + "schema": { + "type": "string" + }, + "description": "\u6dfb\u52a0\u7684\u6d41\u7684\u865a\u62df\u4e3b\u673a\uff0c\u4f8b\u5982__defaultVhost__", + "example": "__defaultVhost__" + }, + { + "name": "app", + "in": "query", + "schema": { + "type": "string" + }, + "description": "\u6dfb\u52a0\u7684\u6d41\u7684\u5e94\u7528\u540d\uff0c\u4f8b\u5982live", + "example": "live" + }, + { + "name": "stream", + "in": "query", + "schema": { + "type": "string" + }, + "description": "\u6dfb\u52a0\u7684\u6d41\u7684id\u540d\uff0c\u4f8b\u5982test", + "example": "test" + }, + { + "name": "file_path", + "in": "query", + "schema": { + "type": "string" + }, + "description": "mp4\u6587\u4ef6\u7edd\u5bf9\u8def\u5f84", + "example": "/path/to/mp4/file.mp4" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": {} + } + } + } + } } } } \ No newline at end of file