Merge pull request 'feat/hk' (#1) from feat/hk into dev
Reviewed-on: #1
This commit is contained in:
commit
b1b3a9a8a2
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@ release/
|
|||||||
.cache
|
.cache
|
||||||
out/
|
out/
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
build_*
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.9)
|
||||||
project(
|
project(
|
||||||
SecMedia
|
SecMedia
|
||||||
VERSION 0.0.1 LANGUAGES C CXX
|
LANGUAGES C CXX
|
||||||
|
VERSION 0.0.1
|
||||||
DESCRIPTION "Security Media Package")
|
DESCRIPTION "Security Media Package")
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
@ -30,6 +31,8 @@ set(CMAKE_C_VISIBILITY_PRESET hidden)
|
|||||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||||
# set(CMAKE_C_FLAGS$ "${CMAKE_C_FLAGS} -fvisibility = hidden")
|
# set(CMAKE_C_FLAGS$ "${CMAKE_C_FLAGS} -fvisibility = hidden")
|
||||||
# set(CMAKE_CXX_FLAGS$ "${CMAKE_CXX_FLAGS} -fvisibility = hidden")
|
# set(CMAKE_CXX_FLAGS$ "${CMAKE_CXX_FLAGS} -fvisibility = hidden")
|
||||||
|
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address
|
||||||
|
# -fno-omit-frame-pointer")
|
||||||
set(SecMedia_Root ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
set(SecMedia_Root ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
add_compile_options(-fPIC)
|
add_compile_options(-fPIC)
|
||||||
# add_compile_options(-fvisibility=hidden) add_compile_options(-std=c++11)
|
# add_compile_options(-fvisibility=hidden) add_compile_options(-std=c++11)
|
||||||
@ -40,23 +43,29 @@ include(GenerateExportHeader)
|
|||||||
|
|
||||||
# media-server ps dec enc
|
# media-server ps dec enc
|
||||||
set(MediaServer_Root ${SecMedia_Root}/3rdpart/media-server)
|
set(MediaServer_Root ${SecMedia_Root}/3rdpart/media-server)
|
||||||
include_directories(${MediaServer_Root}/librtp/include)
|
|
||||||
include_directories(${MediaServer_Root}/libmpeg/include)
|
|
||||||
include_directories(${MediaServer_Root}/libmpeg/source)
|
|
||||||
|
|
||||||
|
add_library(rtp STATIC "")
|
||||||
aux_source_directory(${MediaServer_Root}/libmpeg/include src_rtp)
|
aux_source_directory(${MediaServer_Root}/libmpeg/include src_rtp)
|
||||||
aux_source_directory(${MediaServer_Root}/libmpeg/source src_rtp)
|
aux_source_directory(${MediaServer_Root}/libmpeg/source src_rtp)
|
||||||
aux_source_directory(${MediaServer_Root}/librtp/include src_rtp)
|
aux_source_directory(${MediaServer_Root}/librtp/include src_rtp)
|
||||||
aux_source_directory(${MediaServer_Root}/librtp/source src_rtp)
|
aux_source_directory(${MediaServer_Root}/librtp/source src_rtp)
|
||||||
aux_source_directory(${MediaServer_Root}/librtp/payload src_rtp)
|
aux_source_directory(${MediaServer_Root}/librtp/payload src_rtp)
|
||||||
add_library(rtp STATIC ${src_rtp})
|
target_sources(rtp PRIVATE ${src_rtp})
|
||||||
|
foreach(src ${src_rtp})
|
||||||
|
message(STATUS "rtp src: ${src}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
rtp
|
||||||
|
PUBLIC ${MediaServer_Root}/librtp/include ${MediaServer_Root}/libmpeg/include
|
||||||
|
${MediaServer_Root}/libmpeg/source)
|
||||||
|
|
||||||
include_directories(${SecMedia_Root}/SVAC/src/svac_src)
|
include_directories(${SecMedia_Root}/SVAC/src/svac_src)
|
||||||
# 添加svac解密
|
# 添加svac解密
|
||||||
aux_source_directory(${SecMedia_Root}/SVAC/src/sm2sm3 src_DEC)
|
aux_source_directory(${SecMedia_Root}/SVAC/src/sm2sm3 src_DEC)
|
||||||
aux_source_directory(${SecMedia_Root}/SVAC/src/svac_src src_DEC)
|
aux_source_directory(${SecMedia_Root}/SVAC/src/svac_src src_DEC)
|
||||||
add_library(SVAC_DEC STATIC ${src_DEC})
|
add_library(SVAC_DEC STATIC ${src_DEC})
|
||||||
# 添加svac加密 include_directories(${DEC_ENC_Algorithm}/SVAC/svac_enc) file(GLOB
|
# 添加svac加密 include_directories(${DEC_ENC_Algoruithm}/SVAC/svac_enc) file(GLOB
|
||||||
# src_DEC_ENC ${DEC_ENC_Algorithm}/SVAC/svac_enc/*/*.c
|
# src_DEC_ENC ${DEC_ENC_Algorithm}/SVAC/svac_enc/*/*.c
|
||||||
# ${DEC_ENC_Algorithm}/SVAC/svac_enc/*/*.h)
|
# ${DEC_ENC_Algorithm}/SVAC/svac_enc/*/*.h)
|
||||||
aux_source_directory(${SecMedia_Root}/SVAC/src/sm2sm3_enc src_ENC)
|
aux_source_directory(${SecMedia_Root}/SVAC/src/sm2sm3_enc src_ENC)
|
||||||
@ -75,29 +84,52 @@ include_directories(include src)
|
|||||||
|
|
||||||
# file(GLOB SecMedia_src_list ${SecMedia_Root}/SVAC/./*.c
|
# file(GLOB SecMedia_src_list ${SecMedia_Root}/SVAC/./*.c
|
||||||
# ${SecMedia_Root}/SVAC/./*.h)
|
# ${SecMedia_Root}/SVAC/./*.h)
|
||||||
file(
|
|
||||||
GLOB
|
macro(append_srcs out_var root_dir)
|
||||||
SecMedia_src_list
|
file(GLOB_RECURSE srcs ${root_dir}/*.c ${root_dir}/*.cpp)
|
||||||
${SecMedia_Root}/*/*.cpp
|
list(APPEND ${out_var} ${srcs})
|
||||||
${SecMedia_Root}/*/*.h
|
endmacro(append_srcs)
|
||||||
${SecMedia_Root}/*/*.c
|
|
||||||
${SecMedia_Root}/*/*/*.cpp
|
append_srcs(SecMedia_src_list ${SecMedia_Root}/DecEnc)
|
||||||
${SecMedia_Root}/*/*/*.h
|
append_srcs(SecMedia_src_list ${SecMedia_Root}/Decrypt)
|
||||||
${SecMedia_Root}/*/*/*.c
|
append_srcs(SecMedia_src_list ${SecMedia_Root}/Encrypt)
|
||||||
)
|
append_srcs(SecMedia_src_list ${SecMedia_Root}/GB28181)
|
||||||
|
append_srcs(SecMedia_src_list ${SecMedia_Root}/HuaWei)
|
||||||
|
# append_srcs(SecMedia_src_list ${SecMedia_Root}/SVAC)
|
||||||
|
append_srcs(SecMedia_src_list ${SecMedia_Root}/base)
|
||||||
|
|
||||||
|
# message(STATUS "SRCS: ${SecMedia_src_list}")
|
||||||
|
|
||||||
|
# file( GLOB SecMedia_src_list ${SecMedia_Root}/*/*.cpp ${SecMedia_Root}/*/*.h
|
||||||
|
# ${SecMedia_Root}/*/*.c ${SecMedia_Root}/*/*/*.cpp ${SecMedia_Root}/*/*/*.h
|
||||||
|
# ${SecMedia_Root}/*/*/*.c )
|
||||||
file(GLOB SecMedia_api_list ${CMAKE_CURRENT_SOURCE_DIR}/include/common.h)
|
file(GLOB SecMedia_api_list ${CMAKE_CURRENT_SOURCE_DIR}/include/common.h)
|
||||||
|
|
||||||
# # target_compile_options(${PROJECT_NAME} PRIVATE -fvisibility=hidden)
|
# # target_compile_options(${PROJECT_NAME} PRIVATE -fvisibility=hidden)
|
||||||
# list(APPEND LINK_LIB_LIST ${LINK_LIB_SVAC_LIST})
|
# list(APPEND LINK_LIB_LIST ${LINK_LIB_SVAC_LIST})
|
||||||
|
#
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} SHARED ${SecMedia_src_list})
|
add_library(${PROJECT_NAME} SHARED ${SecMedia_src_list})
|
||||||
# add_library(${PROJECT_NAME} STATIC ${SecMedia_src_list})
|
# add_library(${PROJECT_NAME} STATIC ${SecMedia_src_list})
|
||||||
target_link_libraries(${PROJECT_NAME} ${LINK_LIB_SVAC_LIST} rtp)
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${LINK_LIB_SVAC_LIST} rtp
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${SecMedia_Root}/.)
|
Threads::Threads)
|
||||||
|
target_include_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PRIVATE ${SecMedia_Root}
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/libdash/include
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/libflv/include
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/libhls/include
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/libmov/include
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/libmpeg/include
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/librtmp/include
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/librtp/include
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/librtsp/include
|
||||||
|
${SecMedia_Root}/3rdpart/media-server/libsip/include)
|
||||||
|
|
||||||
# set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION}
|
# set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION}
|
||||||
# SOVERSION 1 PUBLIC_HEADER ${SecMedia_api_list} )
|
# SOVERSION 1 PUBLIC_HEADER ${SecMedia_api_list} ) CXX_VISIBILITY_PRESET hidden
|
||||||
# CXX_VISIBILITY_PRESET hidden CMAKE_C_FLAGS hidden)
|
# CMAKE_C_FLAGS hidden)
|
||||||
|
|
||||||
list(APPEND LINK_LIB_LIST ${PROJECT_NAME})
|
list(APPEND LINK_LIB_LIST ${PROJECT_NAME})
|
||||||
list(APPEND LINK_LIB_LIST pthread)
|
list(APPEND LINK_LIB_LIST pthread)
|
||||||
@ -120,8 +152,9 @@ endif()
|
|||||||
# ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION
|
# ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION
|
||||||
# ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
|
# ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
|
||||||
|
|
||||||
add_subdirectory(test)
|
if(BUILD_TOOLS)
|
||||||
add_subdirectory(PcapSender)
|
add_subdirectory(test)
|
||||||
add_subdirectory(PcapRawSender)
|
add_subdirectory(PcapSender)
|
||||||
add_subdirectory(SecSetGen)
|
add_subdirectory(PcapRawSender)
|
||||||
|
add_subdirectory(SecSetGen)
|
||||||
|
endif(BUILD_TOOLS)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <PcapFileDevice.h>
|
#include <PcapFileDevice.h>
|
||||||
#include <UdpLayer.h>
|
#include <UdpLayer.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <atomic>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -32,7 +33,7 @@ EncrypInit()
|
|||||||
{
|
{
|
||||||
// auto Verify_handle=HWVerify_init();
|
// auto Verify_handle=HWVerify_init();
|
||||||
|
|
||||||
auto sign_handle = GB28181_stream_init(&sign_info);//HWSign_init(&sign_info);
|
auto sign_handle = HK_udp_init(&sign_info);//HWSign_init(&sign_info);
|
||||||
return sign_handle;
|
return sign_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +68,12 @@ template<typename T, typename U>
|
|||||||
timespec
|
timespec
|
||||||
TimeDiff(T &&minu, U &&sub)
|
TimeDiff(T &&minu, U &&sub)
|
||||||
{
|
{
|
||||||
|
if (minu.tv_sec < sub.tv_sec) {
|
||||||
|
return {0, 0};
|
||||||
|
} else if (minu.tv_sec == sub.tv_sec && minu.tv_nsec < sub.tv_nsec) {
|
||||||
|
return {0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
timespec deltatime;
|
timespec deltatime;
|
||||||
deltatime.tv_nsec = minu.tv_nsec - sub.tv_nsec;
|
deltatime.tv_nsec = minu.tv_nsec - sub.tv_nsec;
|
||||||
deltatime.tv_sec = minu.tv_sec - sub.tv_sec;
|
deltatime.tv_sec = minu.tv_sec - sub.tv_sec;
|
||||||
@ -74,7 +81,7 @@ TimeDiff(T &&minu, U &&sub)
|
|||||||
deltatime.tv_nsec += 1000000000;
|
deltatime.tv_nsec += 1000000000;
|
||||||
deltatime.tv_sec--;
|
deltatime.tv_sec--;
|
||||||
}
|
}
|
||||||
return move(deltatime);
|
return deltatime;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -109,6 +116,32 @@ ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const str
|
|||||||
unsigned int sign_out_len;
|
unsigned int sign_out_len;
|
||||||
void *param = nullptr;
|
void *param = nullptr;
|
||||||
uint16_t offset_len, append_len;
|
uint16_t offset_len, append_len;
|
||||||
|
std::shared_ptr<std::thread> output_thread;
|
||||||
|
std::atomic<bool> processing{true};
|
||||||
|
std::atomic<int> processing_cnt{0};
|
||||||
|
if (sign_handle) {
|
||||||
|
output_thread = std::shared_ptr<std::thread>(new std::thread([&] {
|
||||||
|
while (processing.load(std::memory_order_relaxed)) {
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
int ret = HK_udp_out(sign_handle, sign_out_buf, &sign_out_len, &offset_len, &append_len, ¶m);
|
||||||
|
auto end = std::chrono::steady_clock::now();
|
||||||
|
if (ret != 1) { continue; }
|
||||||
|
// WRNGL("HK_udp_out time: %lu ms\n",
|
||||||
|
// std::chrono::duration_cast<std::chrono::microseconds>(end - now).count());
|
||||||
|
processing_cnt.fetch_sub(1);
|
||||||
|
if (append_len == 0) {
|
||||||
|
sendto(socket, sign_out_buf, sign_out_len, 0, (const sockaddr *) &addr, sizeof(addr));
|
||||||
|
} else {
|
||||||
|
sendto(socket, sign_out_buf, offset_len, 0, (const sockaddr *) &addr, sizeof(addr));
|
||||||
|
sendto(socket, sign_out_buf + offset_len, sign_out_len - offset_len, 0, (const sockaddr *) &addr,
|
||||||
|
sizeof(addr));
|
||||||
|
}
|
||||||
|
// HK_udp_in(sign_h2,(char*)payload,payload_len,nullptr);
|
||||||
|
// HK_udp_out(sign_h2,sign_out_buf,&sign_out_len,&offset_len,&append_len, ¶m);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
while (reader->getNextPacket(rawPacket)) {
|
while (reader->getNextPacket(rawPacket)) {
|
||||||
pcpp::Packet parsedPacket(&rawPacket, OsiModelTransportLayer);
|
pcpp::Packet parsedPacket(&rawPacket, OsiModelTransportLayer);
|
||||||
auto layer = parsedPacket.getLayerOfType<UdpLayer>(false);
|
auto layer = parsedPacket.getLayerOfType<UdpLayer>(false);
|
||||||
@ -126,26 +159,16 @@ ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const str
|
|||||||
current_time.tv_sec = inital_time.tv_sec + real_now.tv_sec;
|
current_time.tv_sec = inital_time.tv_sec + real_now.tv_sec;
|
||||||
current_time.tv_nsec = inital_time.tv_nsec + real_now.tv_nsec;
|
current_time.tv_nsec = inital_time.tv_nsec + real_now.tv_nsec;
|
||||||
gaptime = TimeDiff(nowtime, current_time);
|
gaptime = TimeDiff(nowtime, current_time);
|
||||||
if (gaptime.tv_nsec >= 0 && gaptime.tv_sec >= 0) {
|
if (gaptime.tv_nsec > 0 || gaptime.tv_sec > 0) {
|
||||||
nanosleep(&gaptime, NULL);
|
nanosleep(&gaptime, NULL);
|
||||||
} else {
|
} else {
|
||||||
// cout<<" s:" << gaptime.tv_sec<<" ns:" << gaptime.tv_nsec <<endl;
|
// cout<<" s:" << gaptime.tv_sec<<" ns:" << gaptime.tv_nsec <<endl;
|
||||||
}
|
}
|
||||||
// ///////////////calculate send time//////////////////
|
// ///////////////calculate send time//////////////////
|
||||||
if (sign_handle) {
|
if (sign_handle) {
|
||||||
|
auto cnt = processing_cnt.fetch_add(1);
|
||||||
GB28181_stream_in(sign_handle, (char *) payload, payload_len, nullptr);
|
// printf("frame processing cnt:%d\n", cnt);
|
||||||
GB28181_stream_out(sign_handle, sign_out_buf, &sign_out_len, &offset_len, &append_len, ¶m);
|
HK_udp_in(sign_handle, (char *) payload, payload_len, nullptr);
|
||||||
if (append_len == 0) {
|
|
||||||
sendto(socket, sign_out_buf, sign_out_len, 0, (const sockaddr *) &addr, sizeof(addr));
|
|
||||||
} else {
|
|
||||||
sendto(socket, sign_out_buf, offset_len, 0, (const sockaddr *) &addr, sizeof(addr));
|
|
||||||
sendto(socket, sign_out_buf + offset_len, sign_out_len - offset_len, 0, (const sockaddr *) &addr,
|
|
||||||
sizeof(addr));
|
|
||||||
}
|
|
||||||
// GB28181_stream_in(sign_h2,(char*)payload,payload_len,nullptr);
|
|
||||||
// GB28181_stream_out(sign_h2,sign_out_buf,&sign_out_len,&offset_len,&append_len, ¶m);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (sendto(socket, payload, payload_len, 0, (const sockaddr *) &addr, sizeof(addr)) == -1) {
|
if (sendto(socket, payload, payload_len, 0, (const sockaddr *) &addr, sizeof(addr)) == -1) {
|
||||||
printf("send failed : %s\n", strerror(errno));
|
printf("send failed : %s\n", strerror(errno));
|
||||||
@ -156,6 +179,15 @@ ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const str
|
|||||||
// cout<<" stamp:" << rawPacket.getPacketTimeStamp().tv_sec<<" len:"<< rawPacket.getRawDataLen()<<endl;
|
// cout<<" stamp:" << rawPacket.getPacketTimeStamp().tv_sec<<" len:"<< rawPacket.getRawDataLen()<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sign_handle) {
|
||||||
|
while (processing_cnt.load(std::memory_order_relaxed) > 0) {
|
||||||
|
timeval delta = {0, 100000};
|
||||||
|
sleep(delta);
|
||||||
|
}
|
||||||
|
processing.store(false);
|
||||||
|
output_thread->join();
|
||||||
|
}
|
||||||
|
|
||||||
// reader->getNextPacket(rawPacket);
|
// reader->getNextPacket(rawPacket);
|
||||||
|
|
||||||
// for (pcpp::Layer* curLayer = parsedPacket.getFirstLayer(); curLayer != NULL; curLayer = curLayer->getNextLayer())
|
// for (pcpp::Layer* curLayer = parsedPacket.getFirstLayer(); curLayer != NULL; curLayer = curLayer->getNextLayer())
|
||||||
@ -175,31 +207,6 @@ ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const str
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ShowAuthHelper()
|
|
||||||
{
|
|
||||||
struct Config {
|
|
||||||
uint8_t prikey_size;
|
|
||||||
uint8_t pubkey_size;
|
|
||||||
uint8_t prikey[64];
|
|
||||||
uint8_t pubkey[128];
|
|
||||||
} cfg;
|
|
||||||
|
|
||||||
cfg.prikey_size = sign_info.prikey_size;
|
|
||||||
cfg.pubkey_size = sign_info.pubkey_size;
|
|
||||||
memcpy(cfg.prikey, sign_info.prikey, 64);
|
|
||||||
memcpy(cfg.pubkey, sign_info.pubkey, 128);
|
|
||||||
const char *tpl =
|
|
||||||
"http://127.0.0.1/index/api/SetAuthHashCig"
|
|
||||||
"?deviceId=%s"
|
|
||||||
"&KeyVersion=%s"
|
|
||||||
"DecryptType=2"
|
|
||||||
"ConfigData=%s";
|
|
||||||
char out_buf[1024];
|
|
||||||
sprintf(out_buf, tpl, sign_info.camera_id, sign_info.vkek_version, "base64(config)");
|
|
||||||
printf("%s\n", out_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -212,7 +219,6 @@ main(int argc, char *argv[])
|
|||||||
port = atoi(argv[3]);
|
port = atoi(argv[3]);
|
||||||
string filter(argv[4]);
|
string filter(argv[4]);
|
||||||
printf("filename:%s\nip:%s\nport:%d\nfilter:%s\n", filename.data(), ip, port, filter.data());
|
printf("filename:%s\nip:%s\nport:%d\nfilter:%s\n", filename.data(), ip, port, filter.data());
|
||||||
ShowAuthHelper();
|
|
||||||
|
|
||||||
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//SOCK_STREAM
|
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//SOCK_STREAM
|
||||||
if (sockfd == -1) {
|
if (sockfd == -1) {
|
||||||
@ -224,7 +230,7 @@ main(int argc, char *argv[])
|
|||||||
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &rcvBufSize, sizeof(rcvBufSize));
|
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &rcvBufSize, sizeof(rcvBufSize));
|
||||||
if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &rcvBufSize, (socklen_t *) &rcvlen) >= 0) {
|
if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &rcvBufSize, (socklen_t *) &rcvlen) >= 0) {
|
||||||
printf("set udp socket send buff size to : %d\n", rcvBufSize);
|
printf("set udp socket send buff size to : %d\n", rcvBufSize);
|
||||||
if (rcvBufSize < 4194304) { printf("socket send buff too small, please set up to 2097152(2M)\n"); }
|
if (rcvBufSize < 4194304) { printf("socket send buff too small, please set up to 2097152(2M)"); }
|
||||||
} else {
|
} else {
|
||||||
printf("socket failed : %s\n", strerror(errno));
|
printf("socket failed : %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
|||||||
#define _HWSIGN_H
|
#define _HWSIGN_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
//#include <functional>
|
//#include <functional>
|
||||||
#define API_EXPORT __attribute__((visibility("default")))
|
#define API_EXPORT __attribute__((visibility("default")))
|
||||||
@ -21,6 +22,12 @@ struct sec_set_info {
|
|||||||
API_EXPORT int SDF_Device_open();
|
API_EXPORT int SDF_Device_open();
|
||||||
API_EXPORT int SDF_Device_close();
|
API_EXPORT int SDF_Device_close();
|
||||||
|
|
||||||
|
API_EXPORT void *HK_udp_init(struct sec_set_info *sign_info);
|
||||||
|
API_EXPORT int HK_udp_in(void *Handle, const char *buf, const uint32_t len, void *param);
|
||||||
|
API_EXPORT void HK_udp_release(void *Handle);
|
||||||
|
API_EXPORT int
|
||||||
|
HK_udp_out(void *Handle, char *buf, uint32_t *len, uint16_t *sei_end_offset, uint16_t *append_length, void **param);
|
||||||
|
|
||||||
API_EXPORT void *GB28181_stream_init(struct sec_set_info *sign_info);
|
API_EXPORT void *GB28181_stream_init(struct sec_set_info *sign_info);
|
||||||
API_EXPORT int GB28181_stream_in(void *Handle, const char *buf, const uint32_t len, void *param);
|
API_EXPORT int GB28181_stream_in(void *Handle, const char *buf, const uint32_t len, void *param);
|
||||||
API_EXPORT void GB28181_stream_release(void *Handle);
|
API_EXPORT void GB28181_stream_release(void *Handle);
|
||||||
|
47
src/base/event.h
Normal file
47
src/base/event.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef AW_SECURITY_MEDIA_LIB_BASE_EVENT_H
|
||||||
|
#define AW_SECURITY_MEDIA_LIB_BASE_EVENT_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
class Event {
|
||||||
|
public:
|
||||||
|
Event(bool signaled = false) { Reset(signaled); }
|
||||||
|
|
||||||
|
bool Signaled() const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(_lock);
|
||||||
|
return _signaled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wait()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> _(_lock);
|
||||||
|
_cv.wait(_, [this] { return _signaled; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset(bool signaled = false)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(_lock);
|
||||||
|
_signaled = signaled;
|
||||||
|
if (_signaled) { _cv.notify_all(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Signal()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(_lock);
|
||||||
|
_signaled = true;
|
||||||
|
_cv.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable std::mutex _lock;
|
||||||
|
bool _signaled{false};
|
||||||
|
std::condition_variable _cv;
|
||||||
|
};
|
||||||
|
}// namespace sign
|
||||||
|
|
||||||
|
#endif// AW_SECURITY_MEDIA_LIB_BASE_EVENT_H
|
28
src/base/frame.cpp
Normal file
28
src/base/frame.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "frame.h"
|
||||||
|
#include "HuaWei/HWcommon.h"
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
|
||||||
|
static std::atomic<int> g_frame_cnt{0};
|
||||||
|
|
||||||
|
Frame::~Frame() { g_frame_cnt.fetch_sub(1); }
|
||||||
|
|
||||||
|
Frame::Ptr
|
||||||
|
Frame::CreateUDPFrame(const void *data, size_t len)
|
||||||
|
{
|
||||||
|
return std::shared_ptr<Frame>(new Frame(kUDP, data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame::Ptr
|
||||||
|
Frame::CreateTCPFrame(const void *data, size_t len)
|
||||||
|
{
|
||||||
|
return std::shared_ptr<Frame>(new Frame(kTCP, data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame::Frame(Type type, const void *data, size_t len) : _type(type), _data((uint8_t *) data, (uint8_t *) data + len)
|
||||||
|
{
|
||||||
|
auto cur = g_frame_cnt.fetch_add(1);
|
||||||
|
// INFOL("frame count: %d\n", cur);
|
||||||
|
}
|
||||||
|
}// namespace sign
|
64
src/base/frame.h
Normal file
64
src/base/frame.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef AW_SECURITY_MEDIA_LIB_BASE_FRAME_H
|
||||||
|
#define AW_SECURITY_MEDIA_LIB_BASE_FRAME_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "base/event.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
class RTPManager;
|
||||||
|
|
||||||
|
class Frame : std::enable_shared_from_this<Frame> {
|
||||||
|
public:
|
||||||
|
using Ptr = std::shared_ptr<Frame>;
|
||||||
|
|
||||||
|
enum Type { kTCP, kUDP };
|
||||||
|
|
||||||
|
static Ptr CreateUDPFrame(const void *data, size_t len);
|
||||||
|
static Ptr CreateTCPFrame(const void *data, size_t len);
|
||||||
|
|
||||||
|
public:
|
||||||
|
~Frame();
|
||||||
|
|
||||||
|
Type type() const { return _type; }
|
||||||
|
|
||||||
|
const uint8_t *data() const { return _data.data(); }
|
||||||
|
|
||||||
|
uint8_t *data() { return _data.data(); }
|
||||||
|
|
||||||
|
size_t size() const { return _data.size(); }
|
||||||
|
|
||||||
|
// 用户附加的参数
|
||||||
|
void set_user_data(void *param) { _user_data = param; }
|
||||||
|
|
||||||
|
void *user_data() const { return _user_data; }
|
||||||
|
|
||||||
|
bool paused() const { return !_event.Signaled(); }
|
||||||
|
|
||||||
|
// signaled -> unpaused
|
||||||
|
void set_paused(bool paused) { _event.Reset(!paused); }
|
||||||
|
|
||||||
|
void Wait() { _event.Wait(); }
|
||||||
|
|
||||||
|
// For Interface
|
||||||
|
size_t sei_end_offset() const { return _sei_end_offset; }
|
||||||
|
|
||||||
|
size_t append_length() const { return _append_length; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Frame(Type type, const void *data, size_t len);
|
||||||
|
friend class RTPManager;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t _sei_end_offset{0};
|
||||||
|
size_t _append_length{0};
|
||||||
|
|
||||||
|
Event _event{true};
|
||||||
|
Type _type;
|
||||||
|
std::vector<uint8_t> _data;
|
||||||
|
void *_user_data;
|
||||||
|
};
|
||||||
|
}// namespace sign
|
||||||
|
|
||||||
|
#endif// AW_SECURITY_MEDIA_LIB_BASE_FRAME_H
|
69
src/base/frame_manager.cpp
Normal file
69
src/base/frame_manager.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "frame_manager.h"
|
||||||
|
#include "HuaWei/HWcommon.h"
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
|
||||||
|
FrameManager::FrameManager() {}
|
||||||
|
|
||||||
|
FrameManager::~FrameManager() {}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FrameManager::Initialize()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
return _rtp_manager.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FrameManager::Enqueue(Frame::Ptr frame)
|
||||||
|
{
|
||||||
|
CheckMagicNumber();
|
||||||
|
std::lock_guard<std::mutex> _(_frame_queue_lock);
|
||||||
|
OnFrameEnqueue(frame);
|
||||||
|
_frame_queue.push(frame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame::Ptr
|
||||||
|
FrameManager::Dequeue()
|
||||||
|
{
|
||||||
|
CheckMagicNumber();
|
||||||
|
Frame::Ptr frame{nullptr};
|
||||||
|
auto start = std::chrono::system_clock::now();
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(_frame_queue_lock);
|
||||||
|
if (_frame_queue.empty()) { return nullptr; }
|
||||||
|
frame = _frame_queue.front();
|
||||||
|
_frame_queue.pop();
|
||||||
|
OnFrameDequeue(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame->Wait();
|
||||||
|
auto end = std::chrono::system_clock::now();
|
||||||
|
// WRNGL("frame wait time: %ld ms\n", std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count());
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FrameManager::SetSecSetInfo(sec_set_info *info)
|
||||||
|
{
|
||||||
|
_rtp_manager.SetSecSetInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FrameManager::Init()
|
||||||
|
{
|
||||||
|
_rtp_manager.SetHandler(this);
|
||||||
|
OnFrameEnqueue.connect(&_rtp_manager, &RTPManager::OnFrameEnqueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FrameManager::CheckMagicNumber()
|
||||||
|
{
|
||||||
|
if (memcmp(magic_number, "MAGI", 4) != 0) {
|
||||||
|
ERROL("Please Init FrameManager.\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace sign
|
42
src/base/frame_manager.h
Normal file
42
src/base/frame_manager.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef AW_SECURITY_MEDIA_LIB_BASE_FRAME_MANAGER_H
|
||||||
|
#define AW_SECURITY_MEDIA_LIB_BASE_FRAME_MANAGER_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "HuaWei/HWsign.h"
|
||||||
|
#include "base/frame.h"
|
||||||
|
#include "base/rtp_manager.h"
|
||||||
|
#include "sigslot.h"
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
class FrameManager {
|
||||||
|
public:
|
||||||
|
sigslot::signal1<Frame::Ptr> OnFrameEnqueue;
|
||||||
|
sigslot::signal1<Frame::Ptr> OnFrameDequeue;
|
||||||
|
|
||||||
|
FrameManager();
|
||||||
|
~FrameManager();
|
||||||
|
bool Initialize();
|
||||||
|
|
||||||
|
bool Enqueue(Frame::Ptr frame);
|
||||||
|
Frame::Ptr Dequeue();
|
||||||
|
|
||||||
|
// HACK: 透传参数
|
||||||
|
void SetSecSetInfo(sec_set_info *info);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Init();
|
||||||
|
void CheckMagicNumber();
|
||||||
|
|
||||||
|
private:
|
||||||
|
char magic_number[4] = {'M', 'A', 'G', 'I'};
|
||||||
|
RTPManager _rtp_manager;
|
||||||
|
|
||||||
|
std::mutex _frame_queue_lock;
|
||||||
|
std::queue<Frame::Ptr> _frame_queue;
|
||||||
|
};
|
||||||
|
}// namespace sign
|
||||||
|
|
||||||
|
#endif// AW_SECURITY_MEDIA_LIB_BASE_FRAME_MANAGER_H
|
50
src/base/hk_sign.cpp
Normal file
50
src/base/hk_sign.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "HuaWei/HWcommon.h"
|
||||||
|
#include "HuaWei/HWsign.h"
|
||||||
|
#include "base/frame_manager.h"
|
||||||
|
|
||||||
|
void *
|
||||||
|
HK_udp_init(struct sec_set_info *sign_info)
|
||||||
|
{
|
||||||
|
sign::FrameManager *fm = new sign::FrameManager();
|
||||||
|
fm->SetSecSetInfo(sign_info);
|
||||||
|
if (!fm->Initialize()) {
|
||||||
|
delete fm;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return fm;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
HK_udp_in(void *Handle, const char *buf, const uint32_t len, void *param)
|
||||||
|
{
|
||||||
|
sign::FrameManager *fm = (sign::FrameManager *) Handle;
|
||||||
|
INFOL(">>> New Frame <<< \n");
|
||||||
|
auto frame = sign::Frame::CreateUDPFrame(buf, len);
|
||||||
|
if (!frame) {
|
||||||
|
ERROL("Create frame failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fm->Enqueue(frame);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HK_udp_release(void *Handle)
|
||||||
|
{
|
||||||
|
if (Handle) { delete (sign::FrameManager *) Handle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
HK_udp_out(void *Handle, char *buf, uint32_t *len, uint16_t *sei_end_offset, uint16_t *append_length, void **param)
|
||||||
|
{
|
||||||
|
sign::FrameManager *fm = (sign::FrameManager *) Handle;
|
||||||
|
auto frame = fm->Dequeue();
|
||||||
|
if (!frame) { return -1; }
|
||||||
|
|
||||||
|
*len = frame->size();
|
||||||
|
if (buf) { std::copy(frame->data(), frame->data() + frame->size(), buf); }
|
||||||
|
*sei_end_offset = frame->sei_end_offset();
|
||||||
|
*append_length = frame->append_length();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
108
src/base/rtp_decoder.cpp
Normal file
108
src/base/rtp_decoder.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "rtp_decoder.h"
|
||||||
|
#include "HuaWei/HWcommon.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
|
||||||
|
RTPDecoder::Ptr
|
||||||
|
RTPDecoder::Create(int payload_type, const char *encoding)
|
||||||
|
{
|
||||||
|
auto decoder = std::shared_ptr<RTPDecoder>(new RTPDecoder(payload_type, encoding));
|
||||||
|
if (decoder->Initialize()) {
|
||||||
|
return decoder;
|
||||||
|
} else {
|
||||||
|
ERROL("RTPDecoder initialize failed. payload_type=%d, encoding=%s\n", payload_type, encoding);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RTPDecoder::~RTPDecoder() {}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RTPDecoder::Initialize()
|
||||||
|
{
|
||||||
|
_handler = CreateHandler();
|
||||||
|
_decoder = CreateDecoder(_handler);
|
||||||
|
return _handler && _decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPDecoder::Input(RTPPacket::Ptr packet)
|
||||||
|
{
|
||||||
|
if (packet->packet_size() < 12) {
|
||||||
|
WRNGL("RTP packet length is too short. len=%lu\n", packet->packet_size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t pt = GetRTPPayloadType(packet->packet_data());
|
||||||
|
if (pt != _payload_type) {
|
||||||
|
// WRNGL("RTP packet payload type is mismatch. discard it. pt=%d, _payload_type=%d\n", pt, _payload_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t seq = GetRTPSequenceNumber(packet->packet_data());
|
||||||
|
if (_prev_seq == -1) {
|
||||||
|
_prev_seq = seq;
|
||||||
|
_start_decode_tp = std::chrono::steady_clock::now();
|
||||||
|
} else if (seq != ((_prev_seq + 1) & 0xFFFF)) {
|
||||||
|
_start_decode_tp = std::chrono::steady_clock::now();
|
||||||
|
_ref_rtp_packets.clear();
|
||||||
|
_prev_seq = -1;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
_prev_seq = seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ref_rtp_packets.push_back(packet);
|
||||||
|
auto ret = rtp_payload_decode_input(_decoder.get(), packet->packet_data(), packet->packet_size());
|
||||||
|
if (ret < 1) { _ref_rtp_packets.pop_back(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
RTPDecoder::RTPDecoder(int payload_type, const char *encoding) : _payload_type(payload_type), _encoding(encoding) {}
|
||||||
|
|
||||||
|
std::shared_ptr<rtp_payload_t>
|
||||||
|
RTPDecoder::CreateHandler()
|
||||||
|
{
|
||||||
|
auto handler = std::make_shared<rtp_payload_t>();
|
||||||
|
|
||||||
|
handler->alloc = [](void *clazz, int bytes) -> void * {
|
||||||
|
auto self = (RTPDecoder *) clazz;
|
||||||
|
auto &buf = self->_buffer;
|
||||||
|
if (buf.size() < bytes) {
|
||||||
|
buf.resize(bytes);
|
||||||
|
} else if (buf.capacity() > 2 * bytes && bytes > 2048) {
|
||||||
|
buf.shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.data();
|
||||||
|
};
|
||||||
|
|
||||||
|
handler->free = [](void *clazz, void *packet) {};
|
||||||
|
|
||||||
|
handler->packet = [](void *clazz, const void *packet, int bytes, uint32_t timestamp, int flags) {
|
||||||
|
auto self = (RTPDecoder *) clazz;
|
||||||
|
int type = 0x1F & ((uint8_t *) packet)[0];
|
||||||
|
// INFOL("RTPDecoder::CreateHandler packet timestamp=%u, bytes=%d, flags=%d type=%d\n", timestamp, bytes, flags,
|
||||||
|
// type);
|
||||||
|
// std::string hex = ToHex((const uint8_t *) packet, bytes);
|
||||||
|
// INFOL("Data: %s\n", hex.c_str());
|
||||||
|
DecodedPacket dp{packet, bytes, timestamp, flags};
|
||||||
|
dp.ref_rtp_packets.swap(self->_ref_rtp_packets);
|
||||||
|
|
||||||
|
auto end = std::chrono::steady_clock::now();
|
||||||
|
// WRNGL("decode time: %lu ms\n",
|
||||||
|
// std::chrono::duration_cast<std::chrono::milliseconds>(end - self->_start_decode_tp).count());
|
||||||
|
self->OnDecoded(dp);
|
||||||
|
self->_start_decode_tp = std::chrono::steady_clock::now();
|
||||||
|
};
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<void>
|
||||||
|
RTPDecoder::CreateDecoder(std::shared_ptr<rtp_payload_t> handler)
|
||||||
|
{
|
||||||
|
auto rtp_decoder = rtp_payload_decode_create(_payload_type, _encoding.c_str(), handler.get(), this);
|
||||||
|
return std::shared_ptr<void>(rtp_decoder, rtp_payload_decode_destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace sign
|
54
src/base/rtp_decoder.h
Normal file
54
src/base/rtp_decoder.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef AW_SECURITY_MEDIA_LIB_BASE_RTP_DECODER_H
|
||||||
|
#define AW_SECURITY_MEDIA_LIB_BASE_RTP_DECODER_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "rtp-payload.h"
|
||||||
|
#include "rtp_packet.h"
|
||||||
|
#include "sigslot.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
class RTPDecoder {
|
||||||
|
public:
|
||||||
|
using Ptr = std::shared_ptr<RTPDecoder>;
|
||||||
|
|
||||||
|
// void (*packet)(void* param, const void *packet, int bytes, uint32_t timestamp, int flags);
|
||||||
|
struct DecodedPacket {
|
||||||
|
const void *packet;
|
||||||
|
int bytes;
|
||||||
|
uint32_t timestamp;
|
||||||
|
int flags;
|
||||||
|
std::vector<RTPPacket::Ptr> ref_rtp_packets;
|
||||||
|
};
|
||||||
|
|
||||||
|
sigslot::signal1<DecodedPacket> OnDecoded;
|
||||||
|
|
||||||
|
static Ptr Create(int payload_type, const char *encoding = nullptr);
|
||||||
|
|
||||||
|
public:
|
||||||
|
~RTPDecoder();
|
||||||
|
bool Initialize();
|
||||||
|
void Input(RTPPacket::Ptr packet);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RTPDecoder(int payload_type, const char *encoding);
|
||||||
|
std::shared_ptr<rtp_payload_t> CreateHandler();
|
||||||
|
std::shared_ptr<void> CreateDecoder(std::shared_ptr<rtp_payload_t> handler);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _payload_type;
|
||||||
|
std::string _encoding;
|
||||||
|
int32_t _prev_seq{-1};
|
||||||
|
|
||||||
|
std::shared_ptr<void> _decoder;
|
||||||
|
std::shared_ptr<rtp_payload_t> _handler;
|
||||||
|
std::vector<uint8_t> _buffer;
|
||||||
|
|
||||||
|
std::vector<RTPPacket::Ptr> _ref_rtp_packets;
|
||||||
|
std::chrono::steady_clock::time_point _start_decode_tp;
|
||||||
|
};
|
||||||
|
}// namespace sign
|
||||||
|
|
||||||
|
#endif// AW_SECURITY_MEDIA_LIB_BASE_RTP_DECODER_H
|
321
src/base/rtp_manager.cpp
Normal file
321
src/base/rtp_manager.cpp
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
#include "rtp_manager.h"
|
||||||
|
#include "HuaWei/HWcommon.h"
|
||||||
|
#include "base/util.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
RTPManager::RTPManager() {}
|
||||||
|
|
||||||
|
RTPManager::~RTPManager() {}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RTPManager::Initialize()
|
||||||
|
{
|
||||||
|
_signer.OnSigned.connect(this, &RTPManager::OnSigned);
|
||||||
|
return _signer.Start(_sec_set_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::OnFrameEnqueue(Frame::Ptr frame)
|
||||||
|
{
|
||||||
|
if (frame->type() == Frame::kTCP) {
|
||||||
|
ProcessTCPFrame(frame);
|
||||||
|
} else if (frame->type() == Frame::kUDP) {
|
||||||
|
ProcessUDPFrame(frame);
|
||||||
|
} else {
|
||||||
|
// unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::SetSecSetInfo(sec_set_info *info)
|
||||||
|
{
|
||||||
|
_sec_set_info = info;
|
||||||
|
InitSecSet(info);
|
||||||
|
InitVerifySet(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::InitSecSet(void *data)
|
||||||
|
{
|
||||||
|
sec_set_info *info = (sec_set_info *) data;
|
||||||
|
|
||||||
|
uint8_t security_set_version[19] = "Ver 0.0.2";
|
||||||
|
memset(&_sec_set, 0, sizeof(_sec_set));
|
||||||
|
memset(&_sec_set.evek, 0xFF, sizeof(_sec_set.evek));
|
||||||
|
memset(&_sec_set.iv, 0xFF, sizeof(_sec_set.iv));
|
||||||
|
// Set Flag
|
||||||
|
_sec_set.Flag.encryption_flag = 0;
|
||||||
|
_sec_set.Flag.authnetication_flag = 1;
|
||||||
|
_sec_set.Flag.vek_flag = 0;
|
||||||
|
_sec_set.Flag.iv_flag = 0;
|
||||||
|
_sec_set.Flag.hash_discard_p_picture = 1;
|
||||||
|
_sec_set.Flag.reserved_flag = 0b001;
|
||||||
|
// set Type
|
||||||
|
_sec_set.Type.signature_type = (uint8_t) SecMedia::DecryptType::SM2_auth;
|
||||||
|
_sec_set.Type.hash_type = (uint8_t) SecMedia::DecryptType::SM3;
|
||||||
|
_sec_set.Type.encryption_type = (uint8_t) SecMedia::DecryptType::NONE;
|
||||||
|
_sec_set.Type.vek_encryption_type = (uint8_t) SecMedia::DecryptType::NONE;
|
||||||
|
memcpy(_sec_set.camera_id, info->camera_id, sizeof(_sec_set.camera_id));
|
||||||
|
memcpy(_sec_set.vkek_version, info->vkek_version, sizeof(_sec_set.vkek_version));
|
||||||
|
_sec_set.vkek_version_length_minus1 = sizeof(_sec_set.vkek_version) - 1;
|
||||||
|
_sec_set.end_flag = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::InitVerifySet(void *info)
|
||||||
|
{
|
||||||
|
memset(&_verify_set, 0, sizeof(_verify_set));
|
||||||
|
memset(&_verify_set.sign, 0xFF, sizeof(_verify_set.sign));
|
||||||
|
_verify_set.end_flag = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::ProcessUDPFrame(Frame::Ptr frame)
|
||||||
|
{
|
||||||
|
if (!IsRTPHeader(frame->data(), frame->size())) {
|
||||||
|
INFOL("Not a RTP packet. discard it.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
INFOL("RTP info version=%d, payload_type=%d, seq=%d, ssrc=%d\n", GetRTPVersion(frame->data()),
|
||||||
|
GetRTPPayloadType(frame->data()), GetRTPSequenceNumber(frame->data()), GetRTPSSRC(frame->data()));
|
||||||
|
|
||||||
|
auto packet = RTPPacket::CreateCompleteRTPPacket(this, frame);
|
||||||
|
if (packet->payload_type() == 112) {
|
||||||
|
INFOL("RTCP packet pt=112. discard it.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProcessPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::ProcessTCPFrame(Frame::Ptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::ProcessPacket(RTPPacket::Ptr packet)
|
||||||
|
{
|
||||||
|
if (!packet->IsComplete()) {
|
||||||
|
ERROL("RTP packet is not complete, discard it.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeSetSSRC(packet->ssrc());
|
||||||
|
if (packet->ssrc() != _cur_rtp_ssrc) {
|
||||||
|
WRNGL("RTP packet ssrc is mismatch. discard it. handler=%p, cur_ssrc=%ld, packet->ssrc=%d\n", _handler,
|
||||||
|
_cur_rtp_ssrc, packet->ssrc());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeSetSeq(packet->seq());
|
||||||
|
if (packet->seq() != _cur_rtp_seq) {
|
||||||
|
WRNGL("RTP packet seq is not continuous. handler=%p, cur_seq=%ld, packet->seq=%d\n", _handler, _cur_rtp_seq,
|
||||||
|
packet->seq());
|
||||||
|
SetCurSeq(packet->seq());
|
||||||
|
} else {
|
||||||
|
INFOL("RTP packet seq is continuous. handler=%p, cur_seq=%ld, packet->seq=%d\n", _handler, _cur_rtp_seq,
|
||||||
|
packet->seq());
|
||||||
|
}
|
||||||
|
IncCurSeq();
|
||||||
|
|
||||||
|
if (!_decoder) {
|
||||||
|
_decoder = RTPDecoder::Create(packet->payload_type(), "H264");
|
||||||
|
if (_decoder) { _decoder->OnDecoded.connect(this, &RTPManager::OnRTPDecoded); }
|
||||||
|
}
|
||||||
|
if (_decoder) { _decoder->Input(packet); }
|
||||||
|
|
||||||
|
// MaybeReplaceSeq(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::SetCurSeq(uint16_t seq)
|
||||||
|
{
|
||||||
|
_cur_rtp_seq = seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::MaybeSetSSRC(uint32_t ssrc)
|
||||||
|
{
|
||||||
|
if (_cur_rtp_ssrc == -1) { SetCurSSRC(ssrc); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::MaybeSetSeq(uint16_t seq)
|
||||||
|
{
|
||||||
|
if (_cur_rtp_seq == -1) { SetCurSeq(seq); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::MaybeReplaceSeq(RTPPacket::Ptr packet)
|
||||||
|
{
|
||||||
|
auto new_seq = (packet->seq() + _insert_packet_num);
|
||||||
|
packet->set_seq(new_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::SetCurSSRC(uint32_t ssrc)
|
||||||
|
{
|
||||||
|
_cur_rtp_ssrc = ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::IncCurSeq()
|
||||||
|
{
|
||||||
|
_cur_rtp_seq = GetNextSeq();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
RTPManager::GetNextSeq()
|
||||||
|
{
|
||||||
|
return (_cur_rtp_seq + 1) & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
ToString(H264Nal::H264Nal_t type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case H264Nal::NAL_IDR:
|
||||||
|
return "IDR";
|
||||||
|
case H264Nal::NAL_SEI:
|
||||||
|
return "SEI";
|
||||||
|
case H264Nal::NAL_PPS:
|
||||||
|
return "PPS";
|
||||||
|
case H264Nal::NAL_SPS:
|
||||||
|
return "SPS";
|
||||||
|
case H264Nal::NAL_P_B:
|
||||||
|
return "P_B";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::OnRTPDecoded(RTPDecoder::DecodedPacket packet)
|
||||||
|
{
|
||||||
|
uint8_t h264_type = ((uint8_t *) packet.packet)[0] & 0x1F;
|
||||||
|
|
||||||
|
// if (h264_type == 1) { return; }
|
||||||
|
std::stringstream ss;
|
||||||
|
for (auto &p : packet.ref_rtp_packets) {
|
||||||
|
ss << p->seq() << " ";
|
||||||
|
p->set_paused(false);
|
||||||
|
}
|
||||||
|
auto str = ss.str();
|
||||||
|
if (!str.empty()) str.pop_back();
|
||||||
|
INFOL("RTP decoded. handler=%p, type=%s, size=%5u seq=[%s]\n", _handler, ToString((H264Nal::H264Nal_t) h264_type),
|
||||||
|
packet.bytes, str.c_str());
|
||||||
|
if (h264_type == H264Nal::NAL_IDR) {
|
||||||
|
// remove old sign
|
||||||
|
ResetSignData();
|
||||||
|
|
||||||
|
Signer::DataPacket::Ptr sign_packet = std::make_shared<Signer::DataPacket>();
|
||||||
|
sign_packet->param.codec_type = h264_type;
|
||||||
|
sign_packet->param.dts = packet.timestamp;
|
||||||
|
sign_packet->param.data_len = packet.bytes;
|
||||||
|
sign_packet->data = std::vector<uint8_t>((uint8_t *) packet.packet, (uint8_t *) packet.packet + packet.bytes);
|
||||||
|
_signer.Enqueue(sign_packet);
|
||||||
|
} else if (h264_type == H264Nal::NAL_SEI) {
|
||||||
|
INFOL("origin SEI data: %s\n", ToHex((const uint8_t *) packet.packet, packet.bytes).c_str());
|
||||||
|
uint8_t buf[4096];
|
||||||
|
uint8_t *ptr = buf;
|
||||||
|
ptr = SecMedia::appendSEIframe(
|
||||||
|
ptr, SEC_SET_PT, (uint8_t *) SecMedia::Sec_set_UUID, (uint8_t *) (&_sec_set), sizeof(_sec_set));
|
||||||
|
|
||||||
|
auto signed_packet = FetchSignData();
|
||||||
|
if (!signed_packet || signed_packet->sign_data.empty()) {
|
||||||
|
|
||||||
|
if (_signer.state() == Signer::kSigning) {
|
||||||
|
WRNGL("Sign data is empty. still signing\n");
|
||||||
|
_verify_set.head_frame_type = SecMedia::ERR_incomplete_Sign;
|
||||||
|
} else if (!signed_packet) {
|
||||||
|
WRNGL("Sign data is empty. no I-Frame\n");
|
||||||
|
_verify_set.head_frame_type = SecMedia::ERR_Without_Frame_Data;
|
||||||
|
} else {
|
||||||
|
WRNGL("Sign data is empty. no sign_data\n");
|
||||||
|
_verify_set.head_frame_type = SecMedia::ERR_Without_Sign_Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = SecMedia::appendSEIframe(
|
||||||
|
ptr, VER_SET_PT, (uint8_t *) SecMedia::Ver_set_UUID, (uint8_t *) &_verify_set, sizeof(_verify_set));
|
||||||
|
} else {
|
||||||
|
INFOL("Sign data size=%lu\n", signed_packet->sign_data.size());
|
||||||
|
INFOL("Sign data: %s\n", ToHex(signed_packet->sign_data).c_str());
|
||||||
|
_verify_set.head_frame_type = signed_packet->param.codec_type;
|
||||||
|
_verify_set.head_frame_dts = signed_packet->param.dts;
|
||||||
|
_verify_set.total_hash_data_len = signed_packet->param.data_len;
|
||||||
|
_verify_set.sign_len = signed_packet->sign_data.size();
|
||||||
|
memcpy(_verify_set.sign, signed_packet->sign_data.data(), signed_packet->sign_data.size());
|
||||||
|
|
||||||
|
ptr = SecMedia::appendSEIframe(
|
||||||
|
ptr, VER_SET_PT, (uint8_t *) SecMedia::Ver_set_UUID, (uint8_t *) &_verify_set, sizeof(_verify_set));
|
||||||
|
}
|
||||||
|
ModifySEIPacket(packet, buf, ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::ModifySEIPacket(RTPDecoder::DecodedPacket packet, void *sei_begin, void *sei_end)
|
||||||
|
{
|
||||||
|
// TODO: @tqcq 增加对padding udp rtp sei包的处理
|
||||||
|
auto last_packet = packet.ref_rtp_packets.back();
|
||||||
|
auto last_frame = last_packet->ref_frames().back();
|
||||||
|
auto append_len = (const uint8_t *) sei_end - (const uint8_t *) sei_begin;
|
||||||
|
INFOL("Modify SEI packet. seq=%d, size=%lu\n", last_packet->seq(), last_frame->size());
|
||||||
|
INFOL("SEI data size=%lu\n", (uint8_t *) sei_end - (uint8_t *) sei_begin);
|
||||||
|
INFOL("SEI data: %s\n", ToHex((const uint8_t *) sei_begin, append_len).c_str());
|
||||||
|
|
||||||
|
if (last_frame->type() != Frame::kUDP) {
|
||||||
|
ERROL("Only support kUDP");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto &buf = last_frame->_data;
|
||||||
|
|
||||||
|
bool has_padding = last_packet->has_padding();
|
||||||
|
uint8_t padding_len = 0;
|
||||||
|
if (has_padding) {
|
||||||
|
// remove padding
|
||||||
|
padding_len = buf.back();
|
||||||
|
buf.resize(buf.size() - padding_len);
|
||||||
|
}
|
||||||
|
std::copy((uint8_t *) sei_begin, (uint8_t *) sei_end, std::back_inserter(buf));
|
||||||
|
if (has_padding) {
|
||||||
|
// append_len align 4 need (4 - append_len & 0x3)
|
||||||
|
// new_padding_len = (old_padding + append_len_align_len) %4
|
||||||
|
const uint8_t new_padding_len = ((4 - (append_len & 0x3)) + padding_len) % 4;
|
||||||
|
for (int i = 1; i < new_padding_len; ++i) { buf.push_back(0); }
|
||||||
|
buf.push_back(new_padding_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::OnSigned(Signer::SignedPacket::Ptr signed_packet)
|
||||||
|
{
|
||||||
|
INFOL("RTPManager::OnSigned sign data size=%lu\n", signed_packet->sign_data.size());
|
||||||
|
INFOL("RTPManager::OnSigned sign data: %s\n", ToHex(signed_packet->sign_data).c_str());
|
||||||
|
SetSignData(signed_packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::SetSignData(Signer::SignedPacket::Ptr signed_packet)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(_signed_packet_lock);
|
||||||
|
_signed_packet = signed_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPManager::ResetSignData()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(_signed_packet_lock);
|
||||||
|
_signed_packet = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Signer::SignedPacket::Ptr
|
||||||
|
RTPManager::FetchSignData()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(_signed_packet_lock);
|
||||||
|
auto res = _signed_packet;
|
||||||
|
_signed_packet.reset();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace sign
|
94
src/base/rtp_manager.h
Normal file
94
src/base/rtp_manager.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#ifndef AW_SECURITY_MEDIA_LIB_BASE_RTP_MANAGER_H
|
||||||
|
#define AW_SECURITY_MEDIA_LIB_BASE_RTP_MANAGER_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "HuaWei/HWsign.h"
|
||||||
|
#include "rtp_decoder.h"
|
||||||
|
#include "rtp_packet.h"
|
||||||
|
#include "signer.h"
|
||||||
|
#include "sigslot.h"
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
class RTPManager : public sigslot::has_slots<> {
|
||||||
|
public:
|
||||||
|
sigslot::signal1<RTPPacket::Ptr> OnRTPPacket;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RTPManager();
|
||||||
|
~RTPManager();
|
||||||
|
|
||||||
|
bool Initialize();
|
||||||
|
void OnFrameEnqueue(Frame::Ptr frame);
|
||||||
|
|
||||||
|
// HACK:
|
||||||
|
void SetSecSetInfo(sec_set_info *info);
|
||||||
|
|
||||||
|
void SetHandler(void *handler) { _handler = handler; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void InitSecSet(void *info);
|
||||||
|
void InitVerifySet(void *info);
|
||||||
|
|
||||||
|
void ProcessUDPFrame(Frame::Ptr);
|
||||||
|
void ProcessTCPFrame(Frame::Ptr);
|
||||||
|
|
||||||
|
void ProcessPacket(RTPPacket::Ptr packet);
|
||||||
|
|
||||||
|
void SetCurSeq(uint16_t seq);
|
||||||
|
void MaybeSetSSRC(uint32_t ssrc);
|
||||||
|
void MaybeSetSeq(uint16_t seq);
|
||||||
|
void MaybeReplaceSeq(RTPPacket::Ptr packet);
|
||||||
|
|
||||||
|
void SetCurSSRC(uint32_t ssrc);
|
||||||
|
void IncCurSeq();
|
||||||
|
uint16_t GetNextSeq();
|
||||||
|
|
||||||
|
void SetSignData(Signer::SignedPacket::Ptr signed_packet);
|
||||||
|
void ResetSignData();
|
||||||
|
Signer::SignedPacket::Ptr FetchSignData();
|
||||||
|
|
||||||
|
void ModifySEIPacket(RTPDecoder::DecodedPacket packet, void *sei_begin, void *sei_end);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// NALU 组包回调
|
||||||
|
void OnRTPDecoded(RTPDecoder::DecodedPacket packet);
|
||||||
|
|
||||||
|
// 签名数据回调
|
||||||
|
void OnSigned(Signer::SignedPacket::Ptr signed_packet);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Partical RTP packet -> Complete RTP packet -> Decoder -> Signer
|
||||||
|
*
|
||||||
|
* Signer -> RTPManager:
|
||||||
|
* 1. Modify SEI
|
||||||
|
* 2. Insert SEI
|
||||||
|
**/
|
||||||
|
|
||||||
|
void *_handler{nullptr};
|
||||||
|
std::mutex _signed_packet_lock;
|
||||||
|
// std::vector<uint8_t> _sign_data;
|
||||||
|
Signer::SignedPacket::Ptr _signed_packet{nullptr};
|
||||||
|
|
||||||
|
// 当前不完整的RTP包
|
||||||
|
RTPPacket::Ptr _cur_rtp_packet{nullptr};
|
||||||
|
int64_t _cur_rtp_seq{-1};
|
||||||
|
int64_t _cur_rtp_ssrc{-1};
|
||||||
|
|
||||||
|
// 插入的包对seq有影响,需要记录插入包的数量
|
||||||
|
uint16_t _insert_packet_num{0};
|
||||||
|
|
||||||
|
RTPDecoder::Ptr _decoder;
|
||||||
|
|
||||||
|
void *_sec_set_info{nullptr};
|
||||||
|
Signer _signer;
|
||||||
|
|
||||||
|
// 安全相关的辅助信息
|
||||||
|
SecMedia::NALUdecodeInfo _sec_set;
|
||||||
|
// 签名验证信息集合
|
||||||
|
SecMedia::VerificationSet _verify_set;
|
||||||
|
};
|
||||||
|
}// namespace sign
|
||||||
|
|
||||||
|
#endif// AW_SECURITY_MEDIA_LIB_BASE_RTP_MANAGER_H
|
158
src/base/rtp_packet.cpp
Normal file
158
src/base/rtp_packet.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include "rtp_packet.h"
|
||||||
|
#include "HuaWei/HWcommon.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "rtp-packet.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
static std::atomic<int> g_rtp_packet_cnt{0};
|
||||||
|
|
||||||
|
void
|
||||||
|
IncRTPPacketCnt()
|
||||||
|
{
|
||||||
|
auto cnt = g_rtp_packet_cnt.fetch_add(1);
|
||||||
|
// INFOL("rtp packet count: %d\n", cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DecRTPPacketCnt()
|
||||||
|
{
|
||||||
|
g_rtp_packet_cnt.fetch_sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
RTPPacket::Ptr
|
||||||
|
RTPPacket::CreateParticalRTPPacket(RTPManager *owner)
|
||||||
|
{
|
||||||
|
return std::shared_ptr<RTPPacket>(new RTPPacket(owner));
|
||||||
|
}
|
||||||
|
|
||||||
|
RTPPacket::Ptr
|
||||||
|
RTPPacket::CreateCompleteRTPPacket(RTPManager *owner, Frame::Ptr udp_frame)
|
||||||
|
{
|
||||||
|
return std::shared_ptr<RTPPacket>(new RTPPacket(owner, udp_frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
RTPPacket::~RTPPacket()
|
||||||
|
{
|
||||||
|
set_paused(false);
|
||||||
|
DecRTPPacketCnt();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
RTPPacket::packet_size()
|
||||||
|
{
|
||||||
|
assert(_frame_type == Frame::kUDP || state() > kMissTCPHeader);
|
||||||
|
if (_frame_type == Frame::kUDP) {
|
||||||
|
return _ref_frames.front()->size();
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *
|
||||||
|
RTPPacket::packet_data() const
|
||||||
|
{
|
||||||
|
return _rtp_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RTPPacket::has_padding() const
|
||||||
|
{
|
||||||
|
return GetRTPPadding(_rtp_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
RTPPacket::payload_type() const
|
||||||
|
{
|
||||||
|
assert(state() > kMissRTPHeader);
|
||||||
|
return GetRTPPayloadType(_rtp_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
RTPPacket::seq() const
|
||||||
|
{
|
||||||
|
assert(state() > kMissRTPHeader);
|
||||||
|
return GetRTPSequenceNumber(_rtp_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
RTPPacket::ssrc() const
|
||||||
|
{
|
||||||
|
assert(state() > kMissRTPHeader);
|
||||||
|
return GetRTPSSRC(_rtp_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
RTPPacket::timestamp() const
|
||||||
|
{
|
||||||
|
assert(state() > kMissRTPHeader);
|
||||||
|
return GetRTPTimestamp(_rtp_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPPacket::set_seq(uint16_t seq)
|
||||||
|
{
|
||||||
|
if (_frame_type == Frame::kUDP) {
|
||||||
|
SetRTPSequenceNumber(_rtp_ptr, seq);
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPPacket::AddRefFrame(Frame::Ptr frame)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RTPPacket::paused() const
|
||||||
|
{
|
||||||
|
for (auto &frame : _ref_frames) {
|
||||||
|
if (frame->paused()) { return true; }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTPPacket::set_paused(bool paused)
|
||||||
|
{
|
||||||
|
std::for_each(_ref_frames.begin(), _ref_frames.end(), [paused](Frame::Ptr &frame) { frame->set_paused(paused); });
|
||||||
|
}
|
||||||
|
|
||||||
|
RTPPacket::RTPPacket(RTPManager *owner, Frame::Ptr udp_frame)
|
||||||
|
|
||||||
|
{
|
||||||
|
IncRTPPacketCnt();
|
||||||
|
_owner = owner;
|
||||||
|
_ref_frames.push_back(udp_frame);
|
||||||
|
_frame_type = Frame::kUDP;
|
||||||
|
_rtp_ptr = udp_frame->data();
|
||||||
|
_state = IsRTPHeader(udp_frame->data(), udp_frame->size()) ? kComplete : kError;
|
||||||
|
|
||||||
|
udp_frame->set_paused(false);
|
||||||
|
if (_state == kComplete) {
|
||||||
|
rtp_packet_t pkt;
|
||||||
|
if (rtp_packet_deserialize(&pkt, udp_frame->data(), udp_frame->size()) == 0) {
|
||||||
|
_state = kComplete;
|
||||||
|
if (pkt.payloadlen > 0 && pkt.payload) {
|
||||||
|
uint8_t h264_type = ((uint8_t *) pkt.payload)[0] & 0x1F;
|
||||||
|
if (h264_type == H264Nal::NAL_SEI) { udp_frame->set_paused(true); }
|
||||||
|
} else {
|
||||||
|
// WRNGL("rtp packet payload is empty\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_state = kError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RTPPacket::RTPPacket(RTPManager *owner) : _owner(owner), _frame_type(Frame::kTCP) { IncRTPPacketCnt(); }
|
||||||
|
|
||||||
|
}// namespace sign
|
70
src/base/rtp_packet.h
Normal file
70
src/base/rtp_packet.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef AW_SECURITY_MEDIA_LIB_BASE_RTP_H
|
||||||
|
#define AW_SECURITY_MEDIA_LIB_BASE_RTP_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/frame.h"
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
class RTPManager;
|
||||||
|
|
||||||
|
class RTPPacket : std::enable_shared_from_this<RTPPacket> {
|
||||||
|
public:
|
||||||
|
enum State {
|
||||||
|
kError = -1,
|
||||||
|
kMissTCPHeader = 0,
|
||||||
|
kMissRTPHeader = 1,
|
||||||
|
kMissPayload = 2,
|
||||||
|
kComplete = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
using Ptr = std::shared_ptr<RTPPacket>;
|
||||||
|
|
||||||
|
static Ptr CreateParticalRTPPacket(RTPManager *owner);
|
||||||
|
static Ptr CreateCompleteRTPPacket(RTPManager *owner, Frame::Ptr udp_frame);
|
||||||
|
|
||||||
|
public:
|
||||||
|
~RTPPacket();
|
||||||
|
|
||||||
|
State state() const { return _state; }
|
||||||
|
|
||||||
|
bool IsComplete() const { return state() == kComplete; }
|
||||||
|
|
||||||
|
// available on kMissRTPHeader,kMissPayload,kComplete
|
||||||
|
size_t packet_size();
|
||||||
|
const uint8_t *packet_data() const;
|
||||||
|
size_t rtp_payload_size();
|
||||||
|
|
||||||
|
// rtp header, kMissPayload or kComplete
|
||||||
|
bool has_padding() const;
|
||||||
|
uint8_t payload_type() const;
|
||||||
|
uint16_t seq() const;
|
||||||
|
uint32_t ssrc() const;
|
||||||
|
uint32_t timestamp() const;
|
||||||
|
|
||||||
|
void set_seq(uint16_t seq);
|
||||||
|
|
||||||
|
void AddRefFrame(Frame::Ptr frame);
|
||||||
|
|
||||||
|
RTPManager *owner() const { return _owner; }
|
||||||
|
|
||||||
|
bool paused() const;
|
||||||
|
void set_paused(bool paused);
|
||||||
|
|
||||||
|
std::vector<Frame::Ptr> ref_frames() const { return _ref_frames; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
RTPPacket(RTPManager *owner, Frame::Ptr udp_frame);
|
||||||
|
RTPPacket(RTPManager *owner);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RTPManager *_owner{nullptr};
|
||||||
|
uint8_t *_rtp_ptr{nullptr};
|
||||||
|
|
||||||
|
Frame::Type _frame_type;
|
||||||
|
State _state;
|
||||||
|
std::vector<Frame::Ptr> _ref_frames;
|
||||||
|
};
|
||||||
|
}// namespace sign
|
||||||
|
|
||||||
|
#endif// AW_SECURITY_MEDIA_LIB_BASE_RTP_H
|
117
src/base/signer.cpp
Normal file
117
src/base/signer.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include "signer.h"
|
||||||
|
#include "HuaWei/HWcommon.h"
|
||||||
|
#include "HuaWei/HWsign.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
Signer::Signer() {}
|
||||||
|
|
||||||
|
Signer::~Signer()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Signer::Start(void *param)
|
||||||
|
{
|
||||||
|
_param = param;
|
||||||
|
if (_sign_thread) {
|
||||||
|
ERROL("sign thread already running\n");
|
||||||
|
assert(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!_param) {
|
||||||
|
WRNGL("sec_set_info param is null\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 初始化安全相关的辅助信息
|
||||||
|
_sign_thread = std::unique_ptr<std::thread>(new std::thread(&Signer::WorkProc, this));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Signer::Enqueue(DataPacket::Ptr packet)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> _(_sign_lock);
|
||||||
|
_data_queue.push(packet);
|
||||||
|
_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Signer::WorkProc()
|
||||||
|
{
|
||||||
|
sec_set_info *info = reinterpret_cast<sec_set_info *>(_param);
|
||||||
|
if (info) {
|
||||||
|
cpu_set_t mask;
|
||||||
|
CPU_ZERO(&mask);
|
||||||
|
CPU_SET(info->cpu_core, &mask);
|
||||||
|
if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
|
||||||
|
ERROL("set thread affinity failed, target_cpu = %d\n", info->cpu_core);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataPacket::Ptr data_packet;
|
||||||
|
while (!_stopped.load(std::memory_order_relaxed)) {
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> _(_sign_lock);
|
||||||
|
_cv.wait(_, [this] { return !_data_queue.empty() || _stopped; });
|
||||||
|
if (_stopped) { return; }
|
||||||
|
|
||||||
|
_state = kSigning;
|
||||||
|
data_packet.swap(_data_queue.front());
|
||||||
|
_data_queue.pop();
|
||||||
|
}
|
||||||
|
std::vector<uint8_t> sign;
|
||||||
|
if (!Sign(data_packet->data, &sign)) {
|
||||||
|
// do nothing
|
||||||
|
ERROL("sign failed\n");
|
||||||
|
} else {
|
||||||
|
auto signed_packet = std::make_shared<SignedPacket>();
|
||||||
|
signed_packet->param = data_packet->param;
|
||||||
|
signed_packet->sign_data = sign;
|
||||||
|
OnSigned(signed_packet);
|
||||||
|
}
|
||||||
|
_state = kIdle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Signer::Sign(const std::vector<uint8_t> &data, std::vector<uint8_t> *sign)
|
||||||
|
{
|
||||||
|
// 1. sm3 hash
|
||||||
|
std::vector<uint8_t> sm3_hash = SM3Hash(data.data(), data.size());
|
||||||
|
if (sm3_hash.empty() || sm3_hash.size() < 32) {
|
||||||
|
ERROL("sm3 hash failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sec_set_info *info = reinterpret_cast<sec_set_info *>(_param);
|
||||||
|
uint8_t sm2_sign[128];
|
||||||
|
|
||||||
|
do_sm2_sign((char *) info->prikey, (char *) info->pubkey, (char *) sm3_hash.data(), 32, (char *) sm2_sign);
|
||||||
|
sign->assign(sm2_sign, sm2_sign + 64);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Signer::Stop()
|
||||||
|
{
|
||||||
|
_stopped.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Signer::Join()
|
||||||
|
{
|
||||||
|
if (_sign_thread && _sign_thread->joinable()) {
|
||||||
|
_sign_thread->joinable();
|
||||||
|
_sign_thread.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace sign
|
76
src/base/signer.h
Normal file
76
src/base/signer.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#ifndef AW_SECURITY_MEDIA_LIB_BASE_SIGNER_H
|
||||||
|
#define AW_SECURITY_MEDIA_LIB_BASE_SIGNER_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DecEnc/NALUdecode.h"
|
||||||
|
#include "sigslot.h"
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
class Signer {
|
||||||
|
public:
|
||||||
|
enum State {
|
||||||
|
kIdle,
|
||||||
|
kSigning,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SignParam {
|
||||||
|
uint64_t data_len;
|
||||||
|
uint32_t dts;
|
||||||
|
uint8_t codec_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 待签名数据包
|
||||||
|
struct DataPacket {
|
||||||
|
SignParam param;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
using Ptr = std::shared_ptr<DataPacket>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 签名数据包
|
||||||
|
struct SignedPacket {
|
||||||
|
SignParam param;
|
||||||
|
std::vector<uint8_t> sign_data;
|
||||||
|
using Ptr = std::shared_ptr<SignedPacket>;
|
||||||
|
};
|
||||||
|
|
||||||
|
sigslot::signal1<SignedPacket::Ptr> OnSigned;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Signer();
|
||||||
|
virtual ~Signer();
|
||||||
|
|
||||||
|
void Enqueue(DataPacket::Ptr packet);
|
||||||
|
|
||||||
|
bool Start(void *param);
|
||||||
|
void Stop();
|
||||||
|
void Join();
|
||||||
|
|
||||||
|
State state() const { return _state; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void WorkProc();
|
||||||
|
|
||||||
|
bool Sign(const std::vector<uint8_t> &data, std::vector<uint8_t> *sign);
|
||||||
|
|
||||||
|
private:
|
||||||
|
State _state{kIdle};
|
||||||
|
void *_param{nullptr};
|
||||||
|
|
||||||
|
std::atomic<bool> _stopped{false};
|
||||||
|
|
||||||
|
std::unique_ptr<std::thread> _sign_thread{nullptr};
|
||||||
|
|
||||||
|
std::mutex _sign_lock;
|
||||||
|
std::condition_variable _cv;
|
||||||
|
// 存放待签名数据
|
||||||
|
std::queue<DataPacket::Ptr> _data_queue;
|
||||||
|
};
|
||||||
|
}// namespace sign
|
||||||
|
|
||||||
|
#endif// AW_SECURITY_MEDIA_LIB_BASE_SIGNER_H
|
130
src/base/util.cpp
Normal file
130
src/base/util.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#include "util.h"
|
||||||
|
extern "C" {
|
||||||
|
#include "SVAC/src/sm2sm3/sm2.h"
|
||||||
|
}
|
||||||
|
#include "HuaWei/HWcommon.h"
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
uint8_t
|
||||||
|
GetRTPVersion(const uint8_t *data)
|
||||||
|
{
|
||||||
|
return (data[0] & 0xC0) >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
GetRTPPadding(const uint8_t *header)
|
||||||
|
{
|
||||||
|
return (header[0] & 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
GetRTPPayloadType(const uint8_t *data)
|
||||||
|
{
|
||||||
|
return data[1] & 0x7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
GetRTPSequenceNumber(const uint8_t *data)
|
||||||
|
{
|
||||||
|
return (data[2] << 8) | data[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
GetRTPTimestamp(const uint8_t *data)
|
||||||
|
{
|
||||||
|
return (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
GetRTPSSRC(const uint8_t *header)
|
||||||
|
{
|
||||||
|
return (header[8] << 24) | (header[9] << 16) | (header[10] << 8) | header[11];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetRTPSequenceNumber(uint8_t *header, uint16_t seq)
|
||||||
|
{
|
||||||
|
header[2] = seq >> 8;
|
||||||
|
header[3] = seq & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FindRTPOverTCPHeader(const uint8_t *data, size_t len, size_t *header_pos)
|
||||||
|
{
|
||||||
|
if (len <= 0) {
|
||||||
|
return false;
|
||||||
|
} else if (len == 1) {
|
||||||
|
if (data[0] == '$') {
|
||||||
|
*header_pos = 0;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// len >= 2
|
||||||
|
static const uint8_t kRTPOverTCPHeader[] = {'$', 0};
|
||||||
|
uint8_t *ptr = (uint8_t *) memmem(data, len, kRTPOverTCPHeader, sizeof(kRTPOverTCPHeader));
|
||||||
|
if (!ptr) { return false; }
|
||||||
|
*header_pos = ptr - data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsRTPHeader(const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
if (len < 12) {
|
||||||
|
WRNGL("RTP header length error len=%ld", len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetRTPVersion(data) != 2) {
|
||||||
|
INFOL("RTP version error version=%d", GetRTPVersion(data));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsParticalRTPHeader(const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
if (len == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return GetRTPVersion(data) == 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
ToHex(std::vector<uint8_t> data)
|
||||||
|
{
|
||||||
|
return ToHex(data.data(), data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
ToHex(const void *data, size_t len)
|
||||||
|
{
|
||||||
|
static const char hex[] = "0123456789ABCDEF";
|
||||||
|
std::string hex_str;
|
||||||
|
hex_str.resize(len * 2);
|
||||||
|
const uint8_t *ptr = (const uint8_t *) data;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
hex_str[2 * i] = hex[ptr[i] >> 4];
|
||||||
|
hex_str[2 * i + 1] = hex[ptr[i] & 0x0F];
|
||||||
|
}
|
||||||
|
return hex_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t>
|
||||||
|
SM3Hash(const void *data, size_t len)
|
||||||
|
{
|
||||||
|
uint8_t digest[128];
|
||||||
|
sm3_ctx ctx;
|
||||||
|
sm3_init(&ctx);
|
||||||
|
sm3_update(&ctx, (const uint8_t *) data, len);
|
||||||
|
sm3_final(&ctx, digest);
|
||||||
|
return std::vector<uint8_t>(digest, digest + 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace sign
|
32
src/base/util.h
Normal file
32
src/base/util.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef AW_SECURITY_MEDIA_LIB_BASE_UTIL_H
|
||||||
|
#define AW_SECURITY_MEDIA_LIB_BASE_UTIL_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
uint8_t GetRTPVersion(const uint8_t *header);
|
||||||
|
uint8_t GetRTPPadding(const uint8_t *header);
|
||||||
|
uint8_t GetRTPPayloadType(const uint8_t *header);
|
||||||
|
uint16_t GetRTPSequenceNumber(const uint8_t *header);
|
||||||
|
uint32_t GetRTPTimestamp(const uint8_t *header);
|
||||||
|
uint32_t GetRTPSSRC(const uint8_t *header);
|
||||||
|
|
||||||
|
void SetRTPSequenceNumber(uint8_t *header, uint16_t seq);
|
||||||
|
|
||||||
|
bool FindRTPOverTCPHeader(const uint8_t *data, size_t len, size_t *header_pos = nullptr);
|
||||||
|
bool IsRTPHeader(const uint8_t *data, size_t len);
|
||||||
|
bool IsParticalRTPHeader(const uint8_t *data, size_t len);
|
||||||
|
|
||||||
|
std::string ToHex(const void *data, size_t len);
|
||||||
|
std::string ToHex(std::vector<uint8_t> data);
|
||||||
|
|
||||||
|
std::vector<uint8_t> SM3Hash(const void *data, size_t len);
|
||||||
|
|
||||||
|
}// namespace sign
|
||||||
|
|
||||||
|
#endif// AW_SECURITY_MEDIA_LIB_BASE_UTIL_H
|
1682
src/sigslot.h
Normal file
1682
src/sigslot.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user