feat parse h264

This commit is contained in:
tqcq 2024-08-22 14:55:41 +08:00
parent 4d978ac098
commit db52928975
20 changed files with 3288 additions and 618 deletions

View File

@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 3.9)
project(
SecMedia
LANGUAGES C CXX
VERSION 0.0.1
DESCRIPTION "Security Media Package")
set(CMAKE_CXX_STANDARD 11)
@ -83,13 +84,20 @@ file(
${SecMedia_Root}/*/*.c
${SecMedia_Root}/*/*/*.cpp
${SecMedia_Root}/*/*/*.h
${SecMedia_Root}/*/*/*.c)
${SecMedia_Root}/*/*/*.c
)
file(GLOB SecMedia_api_list ${CMAKE_CURRENT_SOURCE_DIR}/include/common.h)
# # target_compile_options(${PROJECT_NAME} PRIVATE -fvisibility=hidden)
# list(APPEND LINK_LIB_LIST ${LINK_LIB_SVAC_LIST})
add_library(${PROJECT_NAME} SHARED ${SecMedia_src_list})
add_library(${PROJECT_NAME} SHARED
"src/base/util.cpp"
"src/base/rtp_packet.cpp"
"src/SVAC/src/sm2sm3/sm3.c"
"src/SVAC/src/sm2sm3/sm2.c"
${SecMedia_src_list}
)
# add_library(${PROJECT_NAME} STATIC ${SecMedia_src_list})
target_link_libraries(${PROJECT_NAME} ${LINK_LIB_SVAC_LIST} rtp)
target_include_directories(${PROJECT_NAME} PRIVATE ${SecMedia_Root}/.)

View File

@ -1,44 +1,46 @@
#include <iostream>
#include "HuaWei/HWsec.h"
#include "HuaWei/HWsign.h"
#include <Packet.h>
#include <PcapFileDevice.h>
#include <UdpLayer.h>
#include <arpa/inet.h>
#include <atomic>
#include <iostream>
#include <stdio.h>
#include <string>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/select.h>
#include "HuaWei/HWsign.h"
#include "HuaWei/HWsec.h"
#include <sys/socket.h>
using namespace std;
using namespace pcpp;
sec_set_info sign_info={
2,
"34020000001320000003",
"2021-07-06T17:27:19.000",
32,
64,
{
0x24,0x88,0xc8,0xdc,0x7f,0xd7,0xe0,0x91,0x30,0x1b,0x5c,0x58,0x2f,0xe7,0x44,0x7d,
0x2f,0x43,0xe4,0xee,0xc8,0x7d,0xc0,0xfb,0xa4,0xb8,0x7d,0x4b,0x8a,0x69,0x7c,0x4e
},
{
0xaa,0xb1,0x3f,0xd7,0x66,0xe2,0x75,0x97,0xc0,0x03,0xe6,0xe4,0x1d,0x77,0x54,0x78,
0xc8,0x29,0xb2,0x0b,0x9e,0xd1,0xff,0xa3,0x6a,0x6f,0xd2,0x7f,0xd6,0x2d,0xaa,0x3f,
0xc9,0x24,0xec,0x6c,0x96,0x0a,0x7b,0x73,0xf6,0xe6,0xfc,0xda,0x3a,0x08,0xfd,0x92,
0xfc,0x00,0x08,0x97,0x78,0x2c,0x71,0x6b,0xe1,0x26,0xf5,0x1e,0xba,0x31,0xf5,0xb2,
}
};
void * EncrypInit(){
sec_set_info sign_info = {
2,
"34020000001320000003",
"2021-07-06T17:27:19.000",
32,
64,
{0x24, 0x88, 0xc8, 0xdc, 0x7f, 0xd7, 0xe0, 0x91, 0x30, 0x1b, 0x5c, 0x58, 0x2f, 0xe7, 0x44, 0x7d,
0x2f, 0x43, 0xe4, 0xee, 0xc8, 0x7d, 0xc0, 0xfb, 0xa4, 0xb8, 0x7d, 0x4b, 0x8a, 0x69, 0x7c, 0x4e},
{
0xaa, 0xb1, 0x3f, 0xd7, 0x66, 0xe2, 0x75, 0x97, 0xc0, 0x03, 0xe6, 0xe4, 0x1d, 0x77, 0x54, 0x78,
0xc8, 0x29, 0xb2, 0x0b, 0x9e, 0xd1, 0xff, 0xa3, 0x6a, 0x6f, 0xd2, 0x7f, 0xd6, 0x2d, 0xaa, 0x3f,
0xc9, 0x24, 0xec, 0x6c, 0x96, 0x0a, 0x7b, 0x73, 0xf6, 0xe6, 0xfc, 0xda, 0x3a, 0x08, 0xfd, 0x92,
0xfc, 0x00, 0x08, 0x97, 0x78, 0x2c, 0x71, 0x6b, 0xe1, 0x26, 0xf5, 0x1e, 0xba, 0x31, 0xf5, 0xb2,
}};
void *
EncrypInit()
{
// auto Verify_handle=HWVerify_init();
auto sign_handle=GB28181_stream_init(&sign_info); //HWSign_init(&sign_info);
auto sign_handle = GB28181_stream_init(&sign_info);//HWSign_init(&sign_info);
return sign_handle;
}
std::string getProtocolTypeAsString(pcpp::ProtocolType protocolType)
std::string
getProtocolTypeAsString(pcpp::ProtocolType protocolType)
{
switch (protocolType)
{
switch (protocolType) {
case pcpp::Ethernet:
return "Ethernet";
case pcpp::IPv4:
@ -53,116 +55,132 @@ std::string getProtocolTypeAsString(pcpp::ProtocolType protocolType)
default:
return "Unknown";
}
}
inline void sleep(timeval & delta){
inline void
sleep(timeval &delta)
{
// delta.tv_sec
select(0,NULL,NULL,NULL,&delta);
select(0, NULL, NULL, NULL, &delta);
}
template<typename T,typename U>
timespec TimeDiff(T && minu,U && sub){
template<typename T, typename U>
timespec
TimeDiff(T &&minu, U &&sub)
{
timespec deltatime;
deltatime.tv_nsec=minu.tv_nsec-sub.tv_nsec;
deltatime.tv_sec=minu.tv_sec-sub.tv_sec;
if(deltatime.tv_nsec<0 && deltatime.tv_sec>0){
deltatime.tv_nsec+=1000000000;
deltatime.tv_nsec = minu.tv_nsec - sub.tv_nsec;
deltatime.tv_sec = minu.tv_sec - sub.tv_sec;
if (deltatime.tv_nsec < 0 && deltatime.tv_sec > 0) {
deltatime.tv_nsec += 1000000000;
deltatime.tv_sec--;
}
return move(deltatime);
}
int ReadPcapAndSend(int socket,sockaddr_in & addr,const string & filename,const string & filter,void * sign_handle){
int
ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const string &filter, void *sign_handle)
{
// auto sign_h2=EncrypInit();
auto reader=pcpp::IFileReaderDevice::getReader(filename);
auto reader = pcpp::IFileReaderDevice::getReader(filename);
// verify that a reader interface was indeed created
if (reader == NULL)
{
if (reader == NULL) {
std::cerr << "Cannot determine reader for file type" << std::endl;
return 1;
}
// open the reader for reading
if (!reader->open())
{
if (!reader->open()) {
std::cerr << "Cannot open input.pcap for reading" << std::endl;
return 1;
}
if (!reader->setFilter(filter))
{
if (!reader->setFilter(filter)) {
std::cerr << "Cannot set filter for file reader" << std::endl;
return 1;
}
uint8_t * payload;
uint8_t *payload;
size_t payload_len;
pcpp::RawPacket rawPacket;
bool first_flag=true;
timespec nowtime,gaptime;
bool first_flag = true;
timespec nowtime, gaptime;
timespec real_now;
timespec inital_time,current_time;
static char sign_out_buf[3096];
timespec inital_time, current_time;
static char sign_out_buf[3096];
unsigned int sign_out_len;
void *param=nullptr;
uint16_t offset_len,append_len;
while (reader->getNextPacket(rawPacket))
{
pcpp::Packet parsedPacket(&rawPacket,OsiModelTransportLayer);
auto layer = parsedPacket.getLayerOfType<UdpLayer>(false);
if(layer){
payload=layer->getLayerPayload();
payload_len=layer->getLayerPayloadSize();
// cout<<" payload_len:" << payload_len<<endl;
nowtime=rawPacket.getPacketTimeStamp();
clock_gettime(CLOCK_MONOTONIC, &real_now);
if(first_flag){
first_flag=false;
inital_time=TimeDiff(nowtime,real_now);
}
current_time.tv_sec=inital_time.tv_sec+real_now.tv_sec;
current_time.tv_nsec=inital_time.tv_nsec+real_now.tv_nsec;
gaptime=TimeDiff(nowtime,current_time);
if (gaptime.tv_nsec>=0 && gaptime.tv_sec>=0)
{
nanosleep(&gaptime,NULL);
}else{
// cout<<" s:" << gaptime.tv_sec<<" ns:" << gaptime.tv_nsec <<endl;
}
// ///////////////calculate send time//////////////////
if(sign_handle){
GB28181_stream_in(sign_handle,(char*)payload,payload_len,nullptr);
GB28181_stream_out(sign_handle,sign_out_buf,&sign_out_len,&offset_len,&append_len, &param);
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));
void *param = nullptr;
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)) {
int ret =
GB28181_stream_out(sign_handle, sign_out_buf, &sign_out_len, &offset_len, &append_len, &param);
if (ret != 1) { continue; }
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));
}
// 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, &param);
}else{
if(sendto(socket,payload,payload_len,0,(const sockaddr*)&addr,sizeof(addr))==-1){
}
}));
}
while (reader->getNextPacket(rawPacket)) {
pcpp::Packet parsedPacket(&rawPacket, OsiModelTransportLayer);
auto layer = parsedPacket.getLayerOfType<UdpLayer>(false);
if (layer) {
payload = layer->getLayerPayload();
payload_len = layer->getLayerPayloadSize();
// cout<<" payload_len:" << payload_len<<endl;
nowtime = rawPacket.getPacketTimeStamp();
clock_gettime(CLOCK_MONOTONIC, &real_now);
if (first_flag) {
first_flag = false;
inital_time = TimeDiff(nowtime, real_now);
}
current_time.tv_sec = inital_time.tv_sec + real_now.tv_sec;
current_time.tv_nsec = inital_time.tv_nsec + real_now.tv_nsec;
gaptime = TimeDiff(nowtime, current_time);
if (gaptime.tv_nsec >= 0 && gaptime.tv_sec >= 0) {
nanosleep(&gaptime, NULL);
} else {
// cout<<" s:" << gaptime.tv_sec<<" ns:" << gaptime.tv_nsec <<endl;
}
// ///////////////calculate send time//////////////////
if (sign_handle) {
auto cnt = processing_cnt.fetch_add(1);
// printf("frame processing cnt:%d\n", cnt);
GB28181_stream_in(sign_handle, (char *) payload, payload_len, nullptr);
} else {
if (sendto(socket, payload, payload_len, 0, (const sockaddr *) &addr, sizeof(addr)) == -1) {
printf("send failed : %s\n", strerror(errno));
}
}
}
// 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);
// for (pcpp::Layer* curLayer = parsedPacket.getFirstLayer(); curLayer != NULL; curLayer = curLayer->getNextLayer())
// {
// std::cout
@ -175,44 +193,43 @@ int ReadPcapAndSend(int socket,sockaddr_in & addr,const string & filename,const
// create the stats object
pcpp::IPcapDevice::PcapStats stats;
reader->getStatistics(stats);
std::cout << "Read " << stats.packetsRecv << " packets successfully and " << stats.packetsDrop << " packets could not be read" << std::flush;
std::cout << "Read " << stats.packetsRecv << " packets successfully and " << stats.packetsDrop
<< " packets could not be read" << std::flush;
return 0;
}
int main(int argc, char *argv[]){
char ip[16] = {0};
int sockfd, port;
if (argc>4)
{
string filename(argv[1]);
strcpy(ip, argv[2]);
port = atoi(argv[3]);
string filter(argv[4]);
printf("filename:%s\nip:%s\nport:%d\nfilter:%s\n", filename.data(), ip,port,filter.data());
sockfd = socket(AF_INET, SOCK_DGRAM , IPPROTO_UDP);//SOCK_STREAM
int
main(int argc, char *argv[])
{
char ip[16] = {0};
int sockfd, port;
if (argc > 4) {
string filename(argv[1]);
strcpy(ip, argv[2]);
port = atoi(argv[3]);
string filter(argv[4]);
printf("filename:%s\nip:%s\nport:%d\nfilter:%s\n", filename.data(), ip, port, filter.data());
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//SOCK_STREAM
if (sockfd == -1) {
printf("create socket failed : %s\n", strerror(errno));
return -1;
}
}
int rcvBufSize = 2097152;
int rcvlen = 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)
{
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &rcvBufSize, sizeof(rcvBufSize));
if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &rcvBufSize, (socklen_t *) &rcvlen) >= 0) {
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)");
}
}else {
printf("socket failed : %s\n", strerror(errno));
if (rcvBufSize < 4194304) { printf("socket send buff too small, please set up to 2097152(2M)"); }
} else {
printf("socket failed : %s\n", strerror(errno));
return -1;
}
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr =inet_addr(ip);
addr.sin_addr.s_addr = inet_addr(ip);
// if(connect(sockfd, (struct sockaddr*)&addr, sizeof(addr))==-1){
// printf("connection error : %s\n", strerror(errno));
// return -1;
@ -220,19 +237,16 @@ int main(int argc, char *argv[]){
// bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
// while (1)
// {
cout.flush();
auto sign_h=EncrypInit();
ReadPcapAndSend(sockfd,addr,filename,filter,sign_h);
cout.flush();
auto sign_h = EncrypInit();
ReadPcapAndSend(sockfd, addr, filename, filter, sign_h);
// }
}
else
{
printf("CMD as: filename.pcap ip port\n");
system("pause");
return 0;
}
} else {
printf("CMD as: filename.pcap ip port\n");
system("pause");
return 0;
}
return 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2,41 +2,58 @@
#ifndef _HWSIGN_H
#define _HWSIGN_H
#include<stdlib.h>
#include<stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
//#include <functional>
#define API_EXPORT __attribute__((visibility("default")))
struct sec_set_info{
struct sec_set_info {
uint8_t cpu_core;
uint8_t camera_id[21];
uint8_t vkek_version[32]; // 秘钥的加密秘钥的版本号
uint8_t camera_id[21];
uint8_t vkek_version[32];// 秘钥的加密秘钥的版本号
uint8_t prikey_size;
uint8_t pubkey_size;
uint8_t prikey[64];
uint8_t pubkey[128];
uint8_t prikey[64];
uint8_t pubkey[128];
};
// void * HWSign_init(const std::function<void(const char * rtp_ptr, const uint32_t rtp_len)> rtp_callback);
API_EXPORT int SDF_Device_open();
API_EXPORT int SDF_Device_close();
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 void GB28181_stream_release(void* Handle);
API_EXPORT int GB28181_stream_out(void* Handle, char * buf, uint32_t * len, uint16_t* sei_end_offset,uint16_t* append_length,void ** param);
API_EXPORT void *HK_stream_init(struct sec_set_info *sign_info);
API_EXPORT int HK_stream_in(void *Handle, const char *buf, const uint32_t len, void *param);
API_EXPORT void HK_stream_release(void *Handle);
API_EXPORT int
KH_stream_out(void *Handle, char *buf, uint32_t *len, uint16_t *sei_end_offset, uint16_t *append_length, void **param);
API_EXPORT void * HWSign_init(struct sec_set_info * sign_info);
API_EXPORT void HWSign_release(void* Handle);
API_EXPORT int HWSign_rtp_input(void* Handle, const char * buf, const uint32_t len, void * param);
API_EXPORT int HWSign_rtp_out(void* Handle, char * buf, uint32_t * len, void ** param);
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 void GB28181_stream_release(void *Handle);
API_EXPORT int GB28181_stream_out(void *Handle,
char *buf,
uint32_t *len,
uint16_t *sei_end_offset,
uint16_t *append_length,
void **param);
API_EXPORT void * HWSign_tcp_init(struct sec_set_info * sign_info);
API_EXPORT void HWSign_tcp_release(void* Handle);
API_EXPORT int HWSign_tcp_rtp_input(void* Handle, const char * buf, const uint32_t len, void * param);
API_EXPORT int HWSign_tcp_rtp_out(void* Handle, char * buf, uint32_t * len, uint16_t* sei_end_offset,uint16_t* append_length,void ** param);
API_EXPORT void *HWSign_init(struct sec_set_info *sign_info);
API_EXPORT void HWSign_release(void *Handle);
API_EXPORT int HWSign_rtp_input(void *Handle, const char *buf, const uint32_t len, void *param);
API_EXPORT int HWSign_rtp_out(void *Handle, char *buf, uint32_t *len, void **param);
API_EXPORT void *HWSign_tcp_init(struct sec_set_info *sign_info);
API_EXPORT void HWSign_tcp_release(void *Handle);
API_EXPORT int HWSign_tcp_rtp_input(void *Handle, const char *buf, const uint32_t len, void *param);
API_EXPORT int HWSign_tcp_rtp_out(void *Handle,
char *buf,
uint32_t *len,
uint16_t *sei_end_offset,
uint16_t *append_length,
void **param);
API_EXPORT void * HWVerify_init();
API_EXPORT void HWVerify_release(void* Handle);
API_EXPORT int HWVerify_rtp_input(void* Handle, const char * buf, const uint32_t len,int tcp, void * param);
API_EXPORT void *HWVerify_init();
API_EXPORT void HWVerify_release(void *Handle);
API_EXPORT int HWVerify_rtp_input(void *Handle, const char *buf, const uint32_t len, int tcp, void *param);
#endif /* _DECRYPT_H */

47
src/base/event.h Normal file
View 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
View 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 uint8_t *data, size_t len)
{
return std::shared_ptr<Frame>(new Frame(kUDP, data, len));
}
Frame::Ptr
Frame::CreateTCPFrame(const uint8_t *data, size_t len)
{
return std::shared_ptr<Frame>(new Frame(kTCP, data, len));
}
Frame::Frame(Type type, const uint8_t *data, size_t len) : _type(type), _data(data, data + len)
{
auto cur = g_frame_cnt.fetch_add(1);
// INFOL("frame count: %d\n", cur);
}
}// namespace sign

53
src/base/frame.h Normal file
View File

@ -0,0 +1,53 @@
#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 Frame : std::enable_shared_from_this<Frame> {
public:
using Ptr = std::shared_ptr<Frame>;
enum Type { kTCP, kUDP };
static Ptr CreateUDPFrame(const uint8_t *data, size_t len);
static Ptr CreateTCPFrame(const uint8_t *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(); }
private:
Frame(Type type, const uint8_t *data, size_t len);
private:
Event _event{true};
Type _type;
std::vector<uint8_t> _data;
void *_user_data;
};
}// namespace sign
#endif// AW_SECURITY_MEDIA_LIB_BASE_FRAME_H

View File

@ -0,0 +1,48 @@
#include "frame_manager.h"
#include "HuaWei/HWcommon.h"
namespace sign {
FrameManager::FrameManager() { Init(); }
FrameManager::~FrameManager() {}
bool
FrameManager::Enqueue(Frame::Ptr frame)
{
std::lock_guard<std::mutex> _(_frame_queue_lock);
OnFrameEnqueue(frame);
_frame_queue.push(frame);
return true;
}
Frame::Ptr
FrameManager::Dequeue()
{
Frame::Ptr frame{nullptr};
{
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();
return frame;
}
void
FrameManager::SetSecSetInfo(sec_set_info *info)
{
_rtp_manager.SetSecSetInfo(info);
}
void
FrameManager::Init()
{
OnFrameEnqueue.connect(&_rtp_manager, &RTPManager::OnFrameEnqueue);
}
}// namespace sign

39
src/base/frame_manager.h Normal file
View File

@ -0,0 +1,39 @@
#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 Enqueue(Frame::Ptr frame);
Frame::Ptr Dequeue();
// HACK: 透传参数
void SetSecSetInfo(sec_set_info *info);
private:
void Init();
private:
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

102
src/base/rtp_decoder.cpp Normal file
View File

@ -0,0 +1,102 @@
#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;
} else if (seq != ((_prev_seq + 1) & 0xFFFF)) {
_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);
self->OnDecoded(dp);
};
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

53
src/base/rtp_decoder.h Normal file
View File

@ -0,0 +1,53 @@
#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;
};
}// namespace sign
#endif// AW_SECURITY_MEDIA_LIB_BASE_RTP_DECODER_H

129
src/base/rtp_manager.cpp Normal file
View File

@ -0,0 +1,129 @@
#include "rtp_manager.h"
#include "HuaWei/HWcommon.h"
#include "base/util.h"
#include <sstream>
namespace sign {
RTPManager::RTPManager() {}
RTPManager::~RTPManager() {}
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)
{}
void
RTPManager::ProcessUDPFrame(Frame::Ptr frame)
{
if (!IsRTPHeader(frame->data(), frame->size())) { return; }
auto packet = RTPPacket::CreateCompleteRTPPacket(this, frame);
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. cur_ssrc=%ld, packet->ssrc=%d\n", _cur_rtp_ssrc,
packet->ssrc());
return;
}
MaybeSetSeq(packet->seq());
if (packet->seq() != _cur_rtp_seq) {
// WRNGL("RTP packet seq is not continuous. cur_seq=%ld, packet->seq=%d\n", _cur_rtp_seq, packet->seq());
SetCurSeq(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;
}
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. type=%2d, size=%5u seq=[%s]\n", h264_type, packet.bytes, str.c_str());
}
}// namespace sign

65
src/base/rtp_manager.h Normal file
View File

@ -0,0 +1,65 @@
#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 "sigslot.h"
namespace sign {
class RTPManager : public sigslot::has_slots<> {
public:
sigslot::signal1<RTPPacket::Ptr> OnRTPPacket;
public:
RTPManager();
~RTPManager();
void OnFrameEnqueue(Frame::Ptr frame);
// HACK:
void SetSecSetInfo(sec_set_info *info);
private:
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();
private:
// FOR TEST
void OnRTPDecoded(RTPDecoder::DecodedPacket packet);
private:
/**
* Partical RTP packet -> Complete RTP packet -> Decoder -> Signer
*
* Signer -> RTPManager:
* 1. Modify SEI
* 2. Insert SEI
**/
// 当前不完整的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;
};
}// namespace sign
#endif// AW_SECURITY_MEDIA_LIB_BASE_RTP_MANAGER_H

134
src/base/rtp_packet.cpp Normal file
View File

@ -0,0 +1,134 @@
#include "rtp_packet.h"
#include "HuaWei/HWcommon.h"
#include "util.h"
#include <algorithm>
#include <atomic>
#include <cassert>
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;
}
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(true);
}
RTPPacket::RTPPacket(RTPManager *owner) : _owner(owner), _frame_type(Frame::kTCP) { IncRTPPacketCnt(); }
}// namespace sign

67
src/base/rtp_packet.h Normal file
View File

@ -0,0 +1,67 @@
#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
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);
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

1
src/base/signer.cpp Normal file
View File

@ -0,0 +1 @@
#include "signer.h"

15
src/base/signer.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef AW_SECURITY_MEDIA_LIB_BASE_SIGNER_H
#define AW_SECURITY_MEDIA_LIB_BASE_SIGNER_H
#pragma once
#include <mutex>
#include <thread>
namespace sign {
class Signer {
public:
};
}// namespace sign
#endif// AW_SECURITY_MEDIA_LIB_BASE_SIGNER_H

110
src/base/util.cpp Normal file
View File

@ -0,0 +1,110 @@
#include "util.h"
extern "C" {
#include "SVAC/src/sm2sm3/sm2.h"
#include "SVAC/src/sm2sm3/sm3.h"
}
namespace sign {
uint8_t
GetRTPVersion(const uint8_t *data)
{
return (data[0] & 0xC0) >> 6;
}
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) { return false; }
if (GetRTPVersion(data) != 2) { 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(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

30
src/base/util.h Normal file
View File

@ -0,0 +1,30 @@
#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 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::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

File diff suppressed because it is too large Load Diff