merge hk_udp

This commit is contained in:
tqcq 2024-09-04 09:55:23 +08:00
commit cabb869f74
19 changed files with 2653 additions and 326 deletions

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
docs/
build*
.gdb_history
.vscode/
build/

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.9)
project(
SecMedia
VERSION 0.0.1
VERSION 0.0.1 LANGUAGES C CXX
DESCRIPTION "Security Media Package")
set(CMAKE_CXX_STANDARD 11)
@ -83,7 +83,8 @@ 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)

View File

@ -74,7 +74,7 @@ TimeDiff(T &&minu, U &&sub)
deltatime.tv_nsec += 1000000000;
deltatime.tv_sec--;
}
return deltatime;
return move(deltatime);
}
int
@ -175,6 +175,31 @@ ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const str
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
main(int argc, char *argv[])
{
@ -187,6 +212,7 @@ main(int argc, char *argv[])
port = atoi(argv[3]);
string filter(argv[4]);
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
if (sockfd == -1) {
@ -198,7 +224,7 @@ main(int argc, char *argv[])
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)"); }
if (rcvBufSize < 4194304) { printf("socket send buff too small, please set up to 2097152(2M)\n"); }
} else {
printf("socket failed : %s\n", strerror(errno));
return -1;

10
doxide.yaml Normal file
View File

@ -0,0 +1,10 @@
title: AW-Security-Media-Lib
description:
files:
- "src/HuaWei/*.h"
- "src/GB28181/*.h"
- "src/DecEnc/*.h"
defines:
API_EXPORT: ""

1682
include/sigslot.h Normal file

File diff suppressed because it is too large Load Diff

44
mkdocs.yaml Normal file
View File

@ -0,0 +1,44 @@
site_name: ASM
site_description:
theme:
name: material
# custom_dir: docs/overrides
features:
- navigation.indexes
palette:
# Palette toggle for light mode
- scheme: default
primary: red
accent: red
toggle:
icon: material/brightness-7
name: Switch to dark mode
# Palette toggle for dark mode
- scheme: slate
primary: red
accent: red
toggle:
icon: material/brightness-4
name: Switch to light mode
markdown_extensions:
- def_list
- attr_list
- admonition
- pymdownx.details
- pymdownx.superfences
- pymdownx.arithmatex:
generic: true
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
plugins:
- search
extra_css:
- stylesheets/doxide.css
extra_javascript:
- javascripts/mathjax.js
- https://polyfill.io/v3/polyfill.min.js?features=es6
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js

View File

@ -1,209 +1,210 @@
#include "L2PSstream.h"
#include "L2PSstream.h"
#include "StreamCodec.h"
#include "mpeg-ps.h"
#include "mpeg-ts-proto.h"
#include "StreamCodec.h"
static inline void nbo_w16(uint8_t* ptr, uint16_t val)
static inline void
nbo_w16(uint8_t *ptr, uint16_t val)
{
ptr[0] = (uint8_t)((val >> 8) & 0xFF);
ptr[1] = (uint8_t)(val & 0xFF);
ptr[0] = (uint8_t) ((val >> 8) & 0xFF);
ptr[1] = (uint8_t) (val & 0xFF);
}
L2PSstream::L2PSstream(sec_set_info* set_info):L2UdpStream(set_info)
L2PSstream::L2PSstream(sec_set_info *set_info) : L2UdpStream(set_info)
{
_ps_demuxer = ps_demuxer_create([](void* param,
int stream,
int codecid,
int flags,
int64_t pts,
int64_t dts,
const void* data,
size_t bytes){
L2PSstream *thiz = (L2PSstream *)param;
thiz->on_ps_decode(stream, codecid,thiz->_ps_demuxer, flags, pts, dts, data, bytes);
return 0;
},this);
_ps_demuxer = ps_demuxer_create(
[](void *param, int stream, int codecid, int flags, int64_t pts, int64_t dts, const void *data, size_t bytes) {
L2PSstream *thiz = (L2PSstream *) param;
thiz->on_ps_decode(stream, codecid, thiz->_ps_demuxer, flags, pts, dts, data, bytes);
return 0;
},
this);
}
L2PSstream::~L2PSstream()
{
ps_demuxer_destroy((struct ps_demuxer_t*)_ps_demuxer);
}
L2PSstream::~L2PSstream() { ps_demuxer_destroy((struct ps_demuxer_t *) _ps_demuxer); }
void L2PSstream::on_rtp_out(const uint8_t *packet, int bytes, uint32_t timestamp, int flags){
// TRACEL("timestamp:%u, bytes:%u, flag:%d\n",timestamp,bytes,flags);
ps_demuxer_input((struct ps_demuxer_t*)_ps_demuxer,packet,bytes);
void
L2PSstream::on_rtp_out(const uint8_t *packet, int bytes, uint32_t timestamp, int flags)
{
TRACEL("timestamp:%u, bytes:%u, flag:%d\n", timestamp, bytes, flags);
ps_demuxer_input((struct ps_demuxer_t *) _ps_demuxer, packet, bytes);
};
void L2PSstream::on_ps_decode(int stream, int codecid, void *ps, int flags, int64_t pts, int64_t dts, const void *data, int bytes){
void
L2PSstream::on_ps_decode(int stream,
int codecid,
void *ps,
int flags,
int64_t pts,
int64_t dts,
const void *data,
int bytes)
{
// TRACEL("dts:%lu, bytes:%d, codecid:%d\n",dts,bytes,codecid);
auto prefix=prefixSize((char*)data,bytes);
auto prefix = prefixSize((char *) data, bytes);
pts /= 90;
dts /= 90;
pts%=((int64_t)UINT32_MAX+1);
dts%=((int64_t)UINT32_MAX+1);
switch (codecid)
{
pts %= ((int64_t) UINT32_MAX + 1);
dts %= ((int64_t) UINT32_MAX + 1);
switch (codecid) {
case PSI_STREAM_H264:
_code_id=CodecId::CodecH264;
stream_split((char*)data,bytes,prefix,[&,dts](const char *ptr, int len, int prefix){
decodeH264(ptr,len,dts,prefix);
});
_code_id = CodecId::CodecH264;
stream_split((char *) data, bytes, prefix,
[&, dts](const char *ptr, int len, int prefix) { decodeH264(ptr, len, dts, prefix); });
break;
case PSI_STREAM_H265:
_code_id=CodecId::CodecH265;
stream_split((char*)data,bytes,prefix,[&](const char *ptr, int len, int prefix){
decodeH265(ptr,len,dts,prefix);
});
_code_id = CodecId::CodecH265;
stream_split((char *) data, bytes, prefix,
[&](const char *ptr, int len, int prefix) { decodeH265(ptr, len, dts, prefix); });
break;
default:
break;
}
}
bool L2PSstream::splitPES(const uint8_t * data, uint16_t len,const std::function<bool(const char *,const char *, int, int)> &cb){
auto prefix=prefixSize((char*)data,len);
uint8_t ned[]={0x00,0x00,0x01,0xe0};
auto start =(uint8_t*)memmem(data, len,ned,sizeof(ned));
char *pes_head=nullptr;
bool ret=false;
ret= stream_split_nd((char*)start,len-(start-data),prefix,ned,sizeof(ned),[&](const char *ptr, int len, int prefix){
pes_head=(char*)ptr;
stream_split((char*)ptr,len,prefix,[&](const char *ptr, int len, int prefix){
//INFOL("%02X %02X %02X %02X %02X \n",(uint8_t)ptr[0],(uint8_t)ptr[1],(uint8_t)ptr[2],(uint8_t)ptr[3],(uint8_t)ptr[4]);
if(cb){
ret=cb(ptr,pes_head,len,prefix);
}else
{
throw runtime_error("empty callback function");
}
bool
L2PSstream::splitPES(const uint8_t *data,
uint16_t len,
const std::function<bool(const char *, const char *, int, int)> &cb)
{
auto prefix = prefixSize((char *) data, len);
uint8_t ned[] = {0x00, 0x00, 0x01, 0xe0};
auto start = (uint8_t *) memmem(data, len, ned, sizeof(ned));
char *pes_head = nullptr;
bool ret = false;
ret = stream_split_nd(
(char *) start, len - (start - data), prefix, ned, sizeof(ned), [&](const char *ptr, int len, int prefix) {
pes_head = (char *) ptr;
stream_split((char *) ptr, len, prefix, [&](const char *ptr, int len, int prefix) {
//INFOL("%02X %02X %02X %02X %02X \n",(uint8_t)ptr[0],(uint8_t)ptr[1],(uint8_t)ptr[2],(uint8_t)ptr[3],(uint8_t)ptr[4]);
if (cb) {
ret = cb(ptr, pes_head, len, prefix);
} else {
throw runtime_error("empty callback function");
}
});
return ret;
});
return ret;
});
if(!ret && start){
record_PES_head(start,len-(start-data));
}
if (!ret && start) { record_PES_head(start, len - (start - data)); }
return ret;
}
void L2PSstream::rtp_post_process(const RTPcell::Ptr &rtp_cell){
const uint8_t h264key[]={0x00,0x00,0x00,0x01,0x65};
const uint8_t PEShead[]={0x00,0x00,0x01,0xe0};
const uint8_t h264Sei[]={0x00,0x00,0x00,0x01,0x06};
uint8_t * keyframe_pos,*PES_pos;
uint16_t payload_len=0;
switch (_code_id)
{
case CodecId::CodecH264:
keyframe_pos =(uint8_t*)memmem(rtp_cell->_PT_data, rtp_cell->_PT_len,h264key,sizeof(h264key));
if(keyframe_pos){ //the rtp contain key frame
auto ret=splitPES(rtp_cell->_PT_data, keyframe_pos-(rtp_cell->_PT_data),[&](const char *ptr,const char *pes, int len, int prefix){
if(prefix==4){
int type=H264_TYPE(((uint8_t *)ptr+prefix)[0]);
if (type==H264Nal::NAL_SEI)
{
uint8_t* sei_ptr=_sei_race_buf;
void
L2PSstream::rtp_post_process(const RTPcell::Ptr &rtp_cell)
{
const uint8_t h264key[] = {0x00, 0x00, 0x00, 0x01, 0x65};
const uint8_t PEShead[] = {0x00, 0x00, 0x01, 0xe0};
const uint8_t h264Sei[] = {0x00, 0x00, 0x00, 0x01, 0x06};
uint8_t *keyframe_pos, *PES_pos;
uint16_t payload_len = 0;
switch (_code_id) {
case CodecId::CodecH264:
keyframe_pos = (uint8_t *) memmem(rtp_cell->_PT_data, rtp_cell->_PT_len, h264key, sizeof(h264key));
if (keyframe_pos) {//the rtp contain key frame
INFOL("Find Key frame\n");
auto ret = splitPES(
rtp_cell->_PT_data, keyframe_pos - (rtp_cell->_PT_data),
[&](const char *ptr, const char *pes, int len, int prefix) {
if (prefix == 4) {
int type = H264_TYPE(((uint8_t *) ptr + prefix)[0]);
if (type == H264Nal::NAL_SEI) {
uint8_t *sei_ptr = _sei_race_buf;
// if(len>sizeof(_sei_race_buf)) return false;
// memcpy(sei_ptr,ptr,len);sei_ptr+=len;
auto gen_ptr=gen_sec_sei(sei_ptr);
if(gen_ptr-sei_ptr<=0) return false;
uint16_t pes_pt_len= (((uint16_t)pes[4]) << 8) | (uint8_t)pes[5];
pes_pt_len+=gen_ptr-sei_ptr;
uint16_t pes_pos=((uint8_t*)pes-rtp_cell->_buffer)+rtp_cell->_RTPpkg_head_pos;
if(pes_pos+2+4>rtp_cell->_RTPpkg_ptr->_buffer.size())
return false;
nbo_w16((uint8_t*)(rtp_cell->_RTPpkg_ptr->_buffer.data()+pes_pos+4),pes_pt_len);
auto gen_ptr = gen_sec_sei(sei_ptr);
if (gen_ptr - sei_ptr <= 0) return false;
uint16_t pes_pt_len = (((uint16_t) pes[4]) << 8) | (uint8_t) pes[5];
pes_pt_len += gen_ptr - sei_ptr;
uint16_t pes_pos = ((uint8_t *) pes - rtp_cell->_buffer) + rtp_cell->_RTPpkg_head_pos;
if (pes_pos + 2 + 4 > rtp_cell->_RTPpkg_ptr->_buffer.size()) return false;
nbo_w16((uint8_t *) (rtp_cell->_RTPpkg_ptr->_buffer.data() + pes_pos + 4), pes_pt_len);
///////////add rear rtp header/////////////////
sei_ptr=addRTPheader(rtp_cell,gen_ptr,sizeof(_sei_race_buf)-(gen_ptr-_sei_race_buf));
if(!sei_ptr) return false;
_sei_race_len=sei_ptr-_sei_race_buf;
rtp_cell->_RTPpkg_ptr->insertData(_sei_race_buf,_sei_race_len,rtp_cell->_RTPpkg_head_pos,
((uint8_t*)ptr-rtp_cell->_buffer)+len,sei_ptr-gen_ptr);
sei_ptr =
addRTPheader(rtp_cell, gen_ptr, sizeof(_sei_race_buf) - (gen_ptr - _sei_race_buf));
if (!sei_ptr) return false;
_sei_race_len = sei_ptr - _sei_race_buf;
rtp_cell->_RTPpkg_ptr->insertData(
_sei_race_buf, _sei_race_len, rtp_cell->_RTPpkg_head_pos,
((uint8_t *) ptr - rtp_cell->_buffer) + len, sei_ptr - gen_ptr);
// SUCSL("SUCESS SIGN!!!!!!!!!!!!!!\n");
return true;
}
}
return false;
});
// PES_pos =(uint8_t*)memmem(rtp_cell->_PT_data, keyframe_pos-(rtp_cell->_PT_data),PEShead,sizeof(PEShead));
// record_PES_head(PES_pos,PES_pos-(rtp_cell->_PT_data));
// if(_PES_head_len>0 ){
// auto sei_head_ptr=_sei_race_buf+_PES_head_len;
// auto pes_ptr=sei_head_ptr+sizeof(h264Sei);
// auto gen_ptr=gen_sec_sei(pes_ptr);
// if(gen_ptr-pes_ptr<=0) return;
// memcpy(sei_head_ptr,h264Sei,sizeof(h264Sei)); // add sei head
// memcpy(_sei_race_buf,_PES_head,_PES_head_len); // add pes head
// payload_len=gen_ptr-_sei_race_buf-6;
// nbo_w16(_sei_race_buf+4,payload_len);// modify pes len
// auto rtp_appen_ptr=addRTPheader(rtp_cell,gen_ptr,sizeof(_sei_race_buf)-(gen_ptr-_sei_race_buf));
// if(rtp_appen_ptr){
// _sei_race_len=rtp_appen_ptr-_sei_race_buf;
// rtp_cell->_RTPpkg_ptr->insertData(_sei_race_buf,_sei_race_len,rtp_cell->_RTPpkg_head_pos,
// rtp_cell->_RTPpkg_head_pos+(PES_pos-rtp_cell->_buffer),rtp_appen_ptr-gen_ptr);
// // SUCSL("SUCESS SIGN!!!!!!!!!!!!!!\n");
// }
// PES_pos =(uint8_t*)memmem(rtp_cell->_PT_data, keyframe_pos-(rtp_cell->_PT_data),PEShead,sizeof(PEShead));
// record_PES_head(PES_pos,PES_pos-(rtp_cell->_PT_data));
// if(_PES_head_len>0 ){
// auto sei_head_ptr=_sei_race_buf+_PES_head_len;
// auto pes_ptr=sei_head_ptr+sizeof(h264Sei);
// auto gen_ptr=gen_sec_sei(pes_ptr);
// if(gen_ptr-pes_ptr<=0) return;
// memcpy(sei_head_ptr,h264Sei,sizeof(h264Sei)); // add sei head
// memcpy(_sei_race_buf,_PES_head,_PES_head_len); // add pes head
// payload_len=gen_ptr-_sei_race_buf-6;
// nbo_w16(_sei_race_buf+4,payload_len);// modify pes len
// auto rtp_appen_ptr=addRTPheader(rtp_cell,gen_ptr,sizeof(_sei_race_buf)-(gen_ptr-_sei_race_buf));
// if(rtp_appen_ptr){
// _sei_race_len=rtp_appen_ptr-_sei_race_buf;
// rtp_cell->_RTPpkg_ptr->insertData(_sei_race_buf,_sei_race_len,rtp_cell->_RTPpkg_head_pos,
// rtp_cell->_RTPpkg_head_pos+(PES_pos-rtp_cell->_buffer),rtp_appen_ptr-gen_ptr);
// // SUCSL("SUCESS SIGN!!!!!!!!!!!!!!\n");
// }
// }
}
break;
case CodecId::CodecH265:
/* code */
break;
case CodecId::CodecInvalid:
break;
default:
WRNGL("unknown code id: %u \n ",_code_id);
break;
// }
} else {
INFOL("NO key frame\n");
}
break;
case CodecId::CodecH265:
/* code */
break;
case CodecId::CodecInvalid:
break;
default:
WRNGL("unknown code id: %u \n ", _code_id);
break;
}
}
void L2PSstream::decodeH264(const char *data, int bytes, int64_t dts, int prefix){
int type=H264_TYPE(((uint8_t *)data+prefix)[0]);
switch (type)
{
void
L2PSstream::decodeH264(const char *data, int bytes, int64_t dts, int prefix)
{
int type = H264_TYPE(((uint8_t *) data + prefix)[0]);
switch (type) {
case H264Nal::NAL_IDR:
TRACEL("NAL_IDR dts:%lu, bytes:%d\n",dts,bytes);
addSignData(data+prefix,bytes-prefix,dts,type);
TRACEL("NAL_IDR dts:%lu, bytes:%d\n", dts, bytes);
addSignData(data + prefix, bytes - prefix, dts, type);
break;
case H264Nal::NAL_SEI:
TRACEL("NAL_SEI dts:%lu, bytes:%d\n",dts,bytes);
break;
default:
break;
}
};
void L2PSstream::decodeH265(const char *data, int bytes, int64_t dts, int prefix){
int type=H265_TYPE(((uint8_t *)data+prefix)[0]);
switch (type)
{
case H265Nal::NAL_BLA_W_LP ... H265Nal::NAL_RSV_IRAP_VCL23: //keyframe
TRACEL("NAL_IDR dts:%lu, bytes:%d\n",dts,bytes);
addSignData(data+prefix,bytes-prefix,dts,type);
break;
case H265Nal::NAL_SEI_PREFIX :
TRACEL("NAL_SEI_PREFIX dts:%lu, bytes:%d\n",dts,bytes);
break;
case H265Nal::NAL_SEI_SUFFIX :
TRACEL("NAL_SEI_SUFFIX dts:%lu, bytes:%d\n",dts,bytes);
TRACEL("NAL_SEI dts:%lu, bytes:%d\n", dts, bytes);
break;
default:
break;
}
};
void
L2PSstream::decodeH265(const char *data, int bytes, int64_t dts, int prefix)
{
int type = H265_TYPE(((uint8_t *) data + prefix)[0]);
switch (type) {
case H265Nal::NAL_BLA_W_LP... H265Nal::NAL_RSV_IRAP_VCL23://keyframe
TRACEL("NAL_IDR dts:%lu, bytes:%d\n", dts, bytes);
addSignData(data + prefix, bytes - prefix, dts, type);
break;
case H265Nal::NAL_SEI_PREFIX:
TRACEL("NAL_SEI_PREFIX dts:%lu, bytes:%d\n", dts, bytes);
break;
case H265Nal::NAL_SEI_SUFFIX:
TRACEL("NAL_SEI_SUFFIX dts:%lu, bytes:%d\n", dts, bytes);
break;
default:
break;
}
};
///////////////////////////////////////////////////////////////////

View File

@ -6,6 +6,8 @@
#include "HuaWei/HWsign.h"
#include "HuaWei/RTP.h"
#include "RtpDecoder.h"
#include "layer2/l2_manager.h"
#include "layer4/rtp_manager.h"
#include <array>
#include <atomic>
#include <fstream>
@ -23,7 +25,7 @@ public:
_keyframe_seq = -2;
_sign_start.notify_all();
usleep(10000);
};
}
void ThreadSign();
@ -55,7 +57,7 @@ protected:
// }
usleep(1000);
// sleep(1);
};
}
private:
const char _class_name[17] = "L2SecurityStream";
@ -67,7 +69,8 @@ protected:
uint32_t _all_out = 0;
bool _keyframe_complete = false;
uint16_t _sei_race_len;
HWsec_queue _package_queue;
// HWsec_queue _package_queue;
L2Manager _l2_manager;
public:
uint8_t _sei_race_buf[4096];
@ -88,10 +91,13 @@ public:
bool _start_sign = false;
};
class L2UdpStream : public L2SecurityStream {
class L2UdpStream : public L2SecurityStream, public sigslot::has_slots<> {
protected:
uint16_t _seq_increment = 0;
RtpDecoder _rtp_decoder;
RTPManager::Ptr _rtp_manager;
L2Manager _l2_manager;
ThreadsafeQueue<RTPpackage::Ptr> _package_queue;
private:
uint16_t _prv_seq = 0;
@ -102,7 +108,11 @@ public:
_rtp_decoder.setOnDecode([&](const uint8_t *packet, int bytes, uint32_t timestamp, int flags) {
on_rtp_out(packet, bytes, timestamp, flags);
});
};
_rtp_manager = std::shared_ptr<RTPManager>(new RTPManager());
_l2_manager.OnFrameInput.connect(_rtp_manager.get(), &RTPManager::OnFrame);
_rtp_manager->OnPSFrame.connect(this, &L2UdpStream::on_rtp_out);
}
int RtpInput(const uint8_t *data, uint16_t len, void *param = nullptr) override;
virtual void on_rtp_out(const uint8_t *packet, int bytes, uint32_t timestamp, int flags) = 0;

View File

@ -1,48 +1,48 @@
#include "RtpDecoder.h"
#include "rtp-payload.h"
RtpDecoder::~RtpDecoder() {
if(_rtp_decoder){
RtpDecoder::~RtpDecoder()
{
if (_rtp_decoder) {
rtp_payload_decode_destroy(_rtp_decoder);
_rtp_decoder = nullptr;
}
}
void RtpDecoder::decodeRtp(const void *data, int bytes) {
if(!_rtp_decoder){
static rtp_payload_t s_func= {
[](void* param, int bytes){
RtpDecoder *obj = (RtpDecoder *)param;
obj->_buffer.resize(bytes);
if (obj->_buffer.capacity()>2*bytes && bytes>2048)
{
obj->_buffer.shrink_to_fit();
}
// obj->_buffer->setCapacity(bytes);
// return (void *)obj->_buffer->data();
return (void*) obj->_buffer.data();
},
[](void* param, void* packet){
//do nothing
},
[](void* param, const void *packet, int bytes, uint32_t timestamp, int flags){
RtpDecoder *obj = (RtpDecoder *)param;
obj->onDecode((uint8_t*)packet,bytes,timestamp,flags);
}
};
void
RtpDecoder::decodeRtp(const void *data, int bytes)
{
if (bytes < 2) { return; }
const uint8_t cur_rtp_type = 0x7F & ((uint8_t *) data)[1];
_rtp_type = 0x7F & ((uint8_t *) data)[1];
INFOL("rtp type:%d\n" ,(int) _rtp_type);
if (!_rtp_decoder) {
static rtp_payload_t s_func = {
[](void *param, int bytes) {
RtpDecoder *obj = (RtpDecoder *) param;
obj->_buffer.resize(bytes);
if (obj->_buffer.capacity() > 2 * bytes && bytes > 2048) { obj->_buffer.shrink_to_fit(); }
// obj->_buffer->setCapacity(bytes);
// return (void *)obj->_buffer->data();
return (void *) obj->_buffer.data();
},
[](void *param, void *packet) {
//do nothing
},
[](void *param, const void *packet, int bytes, uint32_t timestamp, int flags) {
RtpDecoder *obj = (RtpDecoder *) param;
obj->onDecode((uint8_t *) packet, bytes, timestamp, flags);
}};
_rtp_type = cur_rtp_type;
INFOL("rtp type:%d\n", (int) _rtp_type);
_rtp_decoder = rtp_payload_decode_create(_rtp_type, _codec.data(), &s_func, this);
if (!_rtp_decoder) {
WRNGL("unsupported rtp type:%d ,size:%u\n",(int) _rtp_type,bytes);
}
if (!_rtp_decoder) { WRNGL("unsupported rtp type:%d ,size:%u\n", (int) _rtp_type, bytes); }
}
if(_rtp_decoder){
if(( 0x7F & ((uint8_t *) data)[1])==_rtp_type){ // 直接收一种类型了
rtp_payload_decode_input(_rtp_decoder,data,bytes);
if (_rtp_decoder) {
if (cur_rtp_type == _rtp_type) {// 直接收一种类型了
rtp_payload_decode_input(_rtp_decoder, data, bytes);
}
}
}
}

View File

@ -10,13 +10,12 @@ public:
typedef function<void(const uint8_t *packet, int bytes, uint32_t timestamp, int flags)> on_decode_t;
public:
RtpDecoder() {
RtpDecoder(const std::string &codec_name = "MP2P") : _codec(codec_name) {}
};
~RtpDecoder();
void decodeRtp(const void *data, int bytes);
void setOnDecode(on_decode_t cb) { _on_decoded = cb; };
void setOnDecode(on_decode_t cb) { _on_decoded = cb; }
private:
void onDecode(const uint8_t *packet, int bytes, uint32_t timestamp, int flags)
@ -27,7 +26,7 @@ private:
private:
void *_rtp_decoder = nullptr;
std::vector<uint8_t> _buffer;
std::string _codec = "MP2P";
std::string _codec;
uint8_t _rtp_type;
on_decode_t _on_decoded;
};

View File

@ -1,148 +1,149 @@
#ifndef _HWsec_H
#define _HWsec_H
#include <thread>
#include <chrono>
#include <fstream>
#include "HWsign.h"
#include "RTP.h"
#include "queue.h"
#include "HWsign.h"
class HWsec_queue: public ThreadsafeQueue<RTPpackage::Ptr>
{
public:
HWsec_queue(){};
~HWsec_queue(){};
RTPpackage::Ptr pop(){
std::lock_guard<decltype(mutex_)> lock(mutex_);
if (queue_.empty()) {
return nullptr;
}
RTPpackage::Ptr tmp = queue_.front();
if (tmp->isPause())
{
WRNGL("pause@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@pause@@@@@@@@pause@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@pause@@@@@@@@pause@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@pause@@@@@@@@ \n");
return nullptr;
}
queue_.pop();
return tmp;
}
};
#include <chrono>
#include <fstream>
#include <thread>
class HWsec
class HWsec_queue : public ThreadsafeQueue<RTPpackage::Ptr> {
public:
HWsec_queue() {}
~HWsec_queue() {}
RTPpackage::Ptr pop()
{
typedef std::chrono::high_resolution_clock Clock;
private:
CodecId _code_id;
RTPcell::Ptr _SEI_rtp;
RTPcell::Ptr _prv_cell=nullptr;
HWsec_queue _RTPpackage_queue;
uint32_t _all_in=0;
uint32_t _all_out=0;
const char _class_name[6]="HWsec";
bool _keyframe_complete=false;
uint16_t _sei_race_len;
#ifdef DUMP_FILE
shared_ptr<ofstream> _data_file;
shared_ptr<ofstream> _len_file;
#endif
std::thread * _sign_thread;
public:
uint8_t _sei_race_buf[4096];
uint8_t _thread_exit;
int _keyframe_seq;
string _keyframe_DATA;
sm3_ctx _sm3;
sec_set_info _set_info;
SecMedia::NALUdecodeInfo sec_set;
SecMedia::VerificationSet ver_set;
std::mutex _sign_mtx;
std::condition_variable _sign_start;
bool _start_sign=false;
public:
HWsec(sec_set_info* set_info);
~HWsec();
bool check_class(){
return strcmp(_class_name,"HWsec")==0;
std::lock_guard<decltype(mutex_)> lock(mutex_);
if (queue_.empty()) { return nullptr; }
RTPpackage::Ptr tmp = queue_.front();
if (tmp->isPause()) {
WRNGL("pause@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@pause@@@@@@@@pause@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@pause@@@@"
"@@@@pause@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@pause@@@@@@@@ \n");
return nullptr;
}
void HWsec_input(const uint8_t* data,uint16_t len, void *param=nullptr){
RTPpackage::rtp_cb_f rtp_cell_cb=[&](const RTPcell::Ptr &rtp_cell){
if(rtp_cell){
queue_.pop();
return tmp;
}
};
class HWsec {
typedef std::chrono::high_resolution_clock Clock;
private:
CodecId _code_id;
RTPcell::Ptr _SEI_rtp;
RTPcell::Ptr _prv_cell = nullptr;
HWsec_queue _RTPpackage_queue;
uint32_t _all_in = 0;
uint32_t _all_out = 0;
const char _class_name[6] = "HWsec";
bool _keyframe_complete = false;
uint16_t _sei_race_len;
#ifdef DUMP_FILE
shared_ptr<ofstream> _data_file;
shared_ptr<ofstream> _len_file;
#endif
std::thread *_sign_thread;
public:
uint8_t _sei_race_buf[4096];
uint8_t _thread_exit;
int _keyframe_seq;
string _keyframe_DATA;
sm3_ctx _sm3;
sec_set_info _set_info;
SecMedia::NALUdecodeInfo sec_set;
SecMedia::VerificationSet ver_set;
std::mutex _sign_mtx;
std::condition_variable _sign_start;
bool _start_sign = false;
public:
HWsec(sec_set_info *set_info);
~HWsec();
bool check_class() { return strcmp(_class_name, "HWsec") == 0; }
void HWsec_input(const uint8_t *data, uint16_t len, void *param = nullptr)
{
RTPpackage::rtp_cb_f rtp_cell_cb = [&](const RTPcell::Ptr &rtp_cell) {
if (rtp_cell) {
rtp_cell->precessRTP();
switch (rtp_cell->PT)
{
case 99: //h264
if (_code_id!=CodecId::CodecH264)
{
_code_id=CodecId::CodecH264;
switch (rtp_cell->PT) {
case 99://h264
if (_code_id != CodecId::CodecH264) {
_code_id = CodecId::CodecH264;
INFOL("Track type is changed to H.264\n");
}
// decode_264( rtp_cell);
break;
case 103 ... 108: //h265
if (_code_id!=CodecId::CodecH265)
{
_code_id=CodecId::CodecH265;
case 103 ... 108://h265
if (_code_id != CodecId::CodecH265) {
_code_id = CodecId::CodecH265;
INFOL("Track type is changed to H.265\n");
}
decode_265( rtp_cell);
decode_265(rtp_cell);
break;
case 0 ... 95: // standard type
case 0 ... 95:// standard type
break;
default:
WRNGL("Error !!!!!!!!!! Unsupport track type: %u \n",rtp_cell->PT);
WRNGL("Error !!!!!!!!!! Unsupport track type: %u \n", rtp_cell->PT);
break;
}
}else
{
} else {
WRNGL("error");
}
};
#ifdef DUMP_FILE
_data_file->write((char*)data,len);
*_len_file <<len<<endl;
_data_file->flush();
_len_file->flush();
#endif
// DEBUGL("in param address: %p \n",param);
_all_in++;
RTPpackage::Ptr RTPpkg=make_shared<RTPpackage>(rtp_cell_cb,_prv_cell);
};
#ifdef DUMP_FILE
_data_file->write((char *) data, len);
*_len_file << len << endl;
_data_file->flush();
_len_file->flush();
#endif
// DEBUGL("in param address: %p \n",param);
_all_in++;
RTPpackage::Ptr RTPpkg = make_shared<RTPpackage>(rtp_cell_cb, _prv_cell);
// auto t1=Clock::now();
_prv_cell=RTPpkg->assignRTPpackage(data,len,param);
// auto t2=Clock::now();
RTPpkg->insertData();
_RTPpackage_queue.push(RTPpkg);
// auto delta=std::chrono::duration_cast<std::chrono::microseconds>(t2-t1);
// TRACEL("time:%ld size: %lu \n",delta.count(),RTPpkg->_buffer.size());
}
// auto t1=Clock::now();
_prv_cell = RTPpkg->assignRTPpackage(data, len, param);
// auto t2=Clock::now();
RTPpkg->insertData();
_RTPpackage_queue.push(RTPpkg);
// auto delta=std::chrono::duration_cast<std::chrono::microseconds>(t2-t1);
// TRACEL("time:%ld size: %lu \n",delta.count(),RTPpkg->_buffer.size());
}
int HWsec_output(char * buf, uint32_t * len, uint16_t* sei_tail_pos, uint16_t* extra_len, void ** param){
int HWsec_output(char *buf, uint32_t *len, uint16_t *sei_tail_pos, uint16_t *extra_len, void **param)
{
auto element= _RTPpackage_queue.pop();
// *param=nullptr;
if (!element) return -1;
*len=(uint32_t) element->_buffer.size();
memcpy(buf,element->_buffer.data(),*len);
*sei_tail_pos=element->_insert_tail_pos;
*extra_len=element->_inserted_len;
if(param) *param=element->_usr_param;
element->clear_all();
_all_out++;
// DEBUGL("in param address: %p \n",element->_usr_param);
DEBUGL("%p out>> in %u out %u que: %lu frame_len %u tail_pos %u ins_len %u\n",this,_all_in,_all_out, _RTPpackage_queue.size(),*len,*sei_tail_pos,*extra_len);
// DEBUGL("OUT len %u\n", *len);
return 1;
}
private:
void gen_sec_data();
void sign_data(const char * buf, const uint32_t len);
int decode_265(RTPcell::Ptr rtp_cell);
int decode_264(RTPcell::Ptr rtp_cell);
void setfile();
};
auto element = _RTPpackage_queue.pop();
// *param=nullptr;
if (!element) return -1;
*len = (uint32_t) element->_buffer.size();
memcpy(buf, element->_buffer.data(), *len);
*sei_tail_pos = element->_insert_tail_pos;
*extra_len = element->_inserted_len;
if (param) *param = element->_usr_param;
element->clear_all();
_all_out++;
// DEBUGL("in param address: %p \n",element->_usr_param);
DEBUGL("%p out>> in %u out %u que: %lu frame_len %u tail_pos %u ins_len %u\n", this, _all_in, _all_out,
_RTPpackage_queue.size(), *len, *sei_tail_pos, *extra_len);
// DEBUGL("OUT len %u\n", *len);
return 1;
}
private:
void gen_sec_data();
void sign_data(const char *buf, const uint32_t len);
int decode_265(RTPcell::Ptr rtp_cell);
int decode_264(RTPcell::Ptr rtp_cell);
void setfile();
};
#endif //_HWSIGN_TCP_H
#endif//_HWSIGN_TCP_H

39
src/layer2/frame.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "layer2/frame.h"
Frame::Ptr
Frame::CreateUDPFrame(const uint8_t *const data, std::size_t len)
{
return std::shared_ptr<Frame>(new Frame(kUDP, data, len));
}
Frame::Ptr
Frame::CreateTCPFrame(const uint8_t *const data, std::size_t len)
{
return std::shared_ptr<Frame>(new Frame(kTCP, data, len));
}
Frame::Type
Frame::type() const
{
return _type;
}
void *
Frame::user_param() const
{
return _user_param;
}
void
Frame::set_user_param(void *param)
{
_user_param = param;
}
const std::vector<uint8_t> &
Frame::data() const
{
return _data;
}
Frame::Frame(Type type, const uint8_t *const data, std::size_t len) : _type(type), _data(data, data + len) {}

37
src/layer2/frame.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef AW_SECURITY_MEDIA_LIB_LAYER2_FRAME_H
#define AW_SECURITY_MEDIA_LIB_LAYER2_FRAME_H
#pragma once
#include <cstdint>
#include <memory>
#include <vector>
class Frame {
public:
using Ptr = std::shared_ptr<Frame>;
enum Type {
kTCP,
kUDP,
};
static Frame::Ptr CreateUDPFrame(const uint8_t *const data, std::size_t len);
static Frame::Ptr CreateTCPFrame(const uint8_t *const data, std::size_t len);
Type type() const;
const std::vector<uint8_t> &data() const;
void *user_param() const;
void set_user_param(void *param);
private:
Frame(Type type, const uint8_t *const data, std::size_t len);
private:
Type _type;
std::vector<uint8_t> _data;
void *_user_param = nullptr;
};
#endif// AW_SECURITY_MEDIA_LIB_LAYER2_FRAME_H

37
src/layer2/l2_manager.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "l2_manager.h"
#include "HuaWei/HWcommon.h"
void
L2Manager::FrameInput(Frame::Ptr frame)
{
std::lock_guard<std::mutex> _(_mutex);
OnFrameInput(frame);
_frame_queue.push(frame);
}
Frame::Ptr
L2Manager::FrameOutput()
{
std::lock_guard<std::mutex> _(_mutex);
auto frame = _frame_queue.front();
_frame_queue.pop();
OnFrameOutput(_frame_queue.front());
return frame;
}
std::size_t
L2Manager::size() const
{
std::lock_guard<std::mutex> _(_mutex);
return _frame_queue.size();
}
bool
L2Manager::empty() const
{
std::lock_guard<std::mutex> _(_mutex);
return _frame_queue.empty();
}

25
src/layer2/l2_manager.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef AW_SECURITY_MEDIA_LIB_LAYER2_L2_MANAGER_H
#define AW_SECURITY_MEDIA_LIB_LAYER2_L2_MANAGER_H
#pragma once
#include "HuaWei/queue.h"
#include "layer2/frame.h"
#include "sigslot.h"
#include <queue>
class L2Manager {
public:
sigslot::signal1<Frame::Ptr> OnFrameInput;
sigslot::signal1<Frame::Ptr> OnFrameOutput;
void FrameInput(Frame::Ptr frame);
Frame::Ptr FrameOutput();
std::size_t size() const;
bool empty() const;
private:
std::queue<Frame::Ptr> _frame_queue;
mutable std::mutex _mutex;
};
#endif// AW_SECURITY_MEDIA_LIB_LAYER2_L2_MANAGER_H

View File

@ -0,0 +1,77 @@
#include "layer4/rtp_manager.h"
#include "HuaWei/HWcommon.h"
RTPManager::RTPManager() : _stopped(false), _cv(), _mutex(), _packet_queue(), _rtp_decoder()
{
_worker = new std::thread([this] { WorkProc(); });
_rtp_decoder.setOnDecode([this](const uint8_t *packet, int bytes, uint32_t timestamp, int flags) {
OnDecodeCB(packet, bytes, timestamp, flags);
});
}
RTPManager::~RTPManager()
{
_stopped.store(true);
_worker->join();
delete _worker;
}
void
RTPManager::OnFrame(Frame::Ptr frame)
{
RTPPacket::Ptr packet = RTPPacket::CreateUDP(frame->data().data(), frame->data().size());
if (packet->packet_type() == RTPPacket::kTCP) {
WRNGL("Unsupport TCP\n");
} else if (packet->packet_type() == RTPPacket::kUDP) {
if (!packet->PacketIsComplete()) {
INFOL("Incomplete RTP Packet\n");
return;
}
Enqueue(packet);
}
}
void
RTPManager::Enqueue(RTPPacket::Ptr packet)
{
std::lock_guard<std::mutex> _(this->_mutex);
_packet_queue.push(packet);
_cv.notify_all();
}
RTPPacket::Ptr
RTPManager::Dequeue(bool wait)
{
std::unique_lock<std::mutex> _(this->_mutex);
if (wait) {
_cv.wait(_, [this] { return !_packet_queue.empty(); });
} else if (_packet_queue.empty()) {
return nullptr;
}
auto packet = _packet_queue.front();
_packet_queue.pop();
return packet;
}
void
RTPManager::OnDecodeCB(const uint8_t *packet, int bytes, uint32_t timestamp, int flags)
{
TRACEL("RTP Packet: %p, %d, %u, %d\n", packet, bytes, timestamp, flags);
OnPSFrame(packet, bytes, timestamp, flags);
}
void
RTPManager::WorkProc()
{
while (!_stopped.load(std::memory_order_relaxed)) {
RTPPacket::Ptr packet = Dequeue(true);
if (!packet) {
ERROL("RTP Packet is nullptr\n");
continue;
}
TRACEL("RTP Pcket seq: %u , ssrc=%u, len=%lu\n", packet->sequence_number(), packet->ssrc(),
packet->rtp_packet_size());
_rtp_decoder.decodeRtp(packet->rtp_packet(), packet->rtp_packet_size());
}
}

45
src/layer4/rtp_manager.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef AW_SECURITY_MEDIA_LIB_LAYER3_RTP_MANAGER_H
#define AW_SECURITY_MEDIA_LIB_LAYER3_RTP_MANAGER_H
#pragma once
#include "GB28181/RtpDecoder.h"
#include "HuaWei/queue.h"
#include "layer2/frame.h"
#include "layer4/rtp_packet.h"
#include "sigslot.h"
#include <atomic>
class RTPManager : public sigslot::has_slots<> {
public:
// packet, bytes, timestamp, flags
sigslot::signal4<const uint8_t *, int, uint32_t, int> OnPSFrame;
using Ptr = std::shared_ptr<RTPManager>;
public:
RTPManager();
~RTPManager();
void OnFrame(Frame::Ptr frame);
private:
void Enqueue(RTPPacket::Ptr packet);
RTPPacket::Ptr Dequeue(bool wait = true);
void WorkProc();
// typedef function<void(const uint8_t *packet, int bytes, uint32_t timestamp, int flags)> on_decode_t;
void OnDecodeCB(const uint8_t *packet, int bytes, uint32_t timestamp, int flags);
private:
std::atomic<bool> _stopped;
std::thread *_worker;
std::mutex _mutex;
std::condition_variable _cv;
std::queue<RTPPacket::Ptr> _packet_queue;
RtpDecoder _rtp_decoder;
};
#endif// AW_SECURITY_MEDIA_LIB_LAYER3_RTP_MANAGER_H

216
src/layer4/rtp_packet.cpp Normal file
View File

@ -0,0 +1,216 @@
#include "layer4/rtp_packet.h"
#include "HuaWei/HWcommon.h"
#include <arpa/inet.h>
#include <assert.h>
#include <limits>
RTPPacket::Ptr
RTPPacket::CreateUDP(const uint8_t *data, std::size_t len)
{
auto p = std::shared_ptr<RTPPacket>(new RTPPacket(kUDP));
p->Append(data, len);
return p;
}
RTPPacket::Ptr
RTPPacket::CreateTCP(const uint8_t *data, std::size_t len)
{
auto p = std::shared_ptr<RTPPacket>(new RTPPacket(kUDP));
p->Append(data, len);
return p;
}
std::size_t
RTPPacket::GetHeaderSize(PacketType type)
{
switch (type) {
case RTPPacket::kTCP:
return 16;
case RTPPacket::kUDP:
return 12;
default:
ERROL("Unknown packet type.\n");
return std::numeric_limits<std::size_t>::max();
}
}
RTPPacket::~RTPPacket() {}
bool
RTPPacket::CanBeParsed() const
{
if (_data.empty()) { return true; }
if (packet_type() == kTCP) {
if (_data[0] != '$') { return false; }
if (_data.size() >= 5 && version() != 2) { return false; }
} else if (packet_type() == kUDP) {
if (version() != 2) { return false; }
} else {
return false;
}
return true;
}
bool
RTPPacket::FixedHeaderIsComplete() const
{
if (!CanBeParsed()) { return false; }
if (GetHeaderSize(packet_type()) > _data.size()) { return false; }
return true;
}
bool
RTPPacket::HeaderIsComplete() const
{
if (!FixedHeaderIsComplete()) {
TRACEL("FixedHeader not is complete.\n");
return false;
}
const std::size_t base_header_len = GetHeaderSize(packet_type());
// 首先检查固定头长度
const std::size_t fixed_header_len = base_header_len + csrc_count() * 4;
if (_data.size() < fixed_header_len) { return false; }
// 检查扩展头长度
if (has_extension()) {
if (_data.size() < fixed_header_len + 4) { return false; }
const std::size_t header_len = fixed_header_len + 4 + extension_length();
if (_data.size() < header_len) { return false; }
}
return true;
}
bool
RTPPacket::PacketIsComplete() const
{
if (!HeaderIsComplete()) { return false; }
// tcp 需要检查后续长度是否满足 tcp_payload_size
if (packet_type() == kTCP && tcp_payload_size() + 4 > _data.size()) { return false; }
// 如果已经是整个rtp packet检查 padding
// if (has_padding()) {
// const std::size_t padding_len = _data.back();
// if (padding_len > _data.size() - rtp_fixed_header_size()) { return false; }
// }
return true;
}
void
RTPPacket::Append(const uint8_t *const data, std::size_t len)
{
std::copy(data, data + len, std::back_inserter(_data));
}
std::size_t
RTPPacket::lack_len() const
{
if (packet_type() == kTCP) {
if (FixedHeaderIsComplete()) {}
}
return 0;
}
std::uint8_t
RTPPacket::version() const
{
return *rtp_header() >> 6;
}
bool
RTPPacket::has_padding() const
{
return *rtp_header() & 0x20;
}
bool
RTPPacket::has_extension() const
{
return *rtp_header() & 0x10;
}
std::uint8_t
RTPPacket::csrc_count() const
{
uint8_t cnt = *rtp_header() & 0x0f;
return cnt;
}
bool
RTPPacket::has_marker() const
{
return *(rtp_header() + 1) & 0x80;
}
std::uint8_t
RTPPacket::payload_type() const
{
return *(rtp_header() + 1) & 0x7f;
}
std::uint16_t
RTPPacket::sequence_number() const
{
uint16_t *p = (uint16_t *) (rtp_header() + 2);
return ntohs(*p);
}
std::uint32_t
RTPPacket::timestamp() const
{
uint32_t *p = (uint32_t *) (rtp_header() + 4);
return ntohl(*p);
}
std::uint32_t
RTPPacket::ssrc() const
{
uint32_t *p = (uint32_t *) (rtp_header() + 8);
return ntohl(*p);
}
std::size_t
RTPPacket::tcp_payload_size() const
{
assert(_type == kTCP && "Must be TCP packet.\n");
if (CanBeParsed() && _data.size() >= 4) { return ntohs(*(uint16_t *) (_data.data() + 2)); }
return 0;
}
std::uint8_t *
RTPPacket::rtp_packet() const
{
return rtp_header();
}
std::size_t
RTPPacket::rtp_packet_size() const
{
return _data.size() - _rtp_header_offset;
}
std::uint8_t *
RTPPacket::rtp_header() const
{
return const_cast<std::uint8_t *>(_data.data()) + _rtp_header_offset;
}
std::size_t
RTPPacket::rtp_fixed_header_size() const
{
return 12 + csrc_count() * 4;
}
std::size_t
RTPPacket::extension_length() const
{
if (!has_extension()) { return 0; }
auto extension_header = rtp_header() + rtp_fixed_header_size();
uint16_t *p = (uint16_t *) (extension_header + 2);
return ntohs(*p);
}
RTPPacket::RTPPacket(PacketType type) : _type(type), _rtp_header_offset(type == kTCP ? 4 : 0) {}

75
src/layer4/rtp_packet.h Normal file
View File

@ -0,0 +1,75 @@
#ifndef AW_SECURITY_MEDIA_LIB_LAYER3_RTP_PACKET_H
#define AW_SECURITY_MEDIA_LIB_LAYER3_RTP_PACKET_H
#pragma once
#include <cstdint>
#include <memory>
#include <vector>
class RTPPacket {
public:
using Ptr = std::shared_ptr<RTPPacket>;
enum PacketType {
kTCP,
kUDP,
};
class RTPHeaderExtension {
public:
RTPHeaderExtension(RTPPacket::Ptr rtp_packet);
std::uint16_t profile();
std::uint16_t length();
std::uint16_t data();
};
public:
static RTPPacket::Ptr CreateUDP(const uint8_t *data, std::size_t len);
static RTPPacket::Ptr CreateTCP(const uint8_t *data, std::size_t len);
static std::size_t GetHeaderSize(PacketType type);
~RTPPacket();
bool CanBeParsed() const;
bool FixedHeaderIsComplete() const;
bool HeaderIsComplete() const;
bool PacketIsComplete() const;
void Append(const uint8_t *const data, std::size_t len);
std::size_t lack_len() const;
PacketType packet_type() const { return _type; }
// Header Info
std::uint8_t version() const;
bool has_padding() const;
bool has_extension() const;
std::uint8_t csrc_count() const;
bool has_marker() const;
std::uint8_t payload_type() const;
std::uint16_t sequence_number() const;
std::uint32_t timestamp() const;
std::uint32_t ssrc() const;
std::size_t tcp_payload_size() const;
std::uint8_t *rtp_packet() const;
std::size_t rtp_packet_size() const;
std::size_t rtp_fixed_header_size() const;
std::size_t extension_length() const;
std::size_t padding_length() const;
private:
RTPPacket(PacketType type);
std::uint8_t *rtp_header() const;
private:
PacketType _type;
std::vector<std::uint8_t> _data;
// for tcp: offset = 4
// for udp: offset = 0
std::size_t _rtp_header_offset;
};
#endif// AW_SECURITY_MEDIA_LIB_LAYER3_RTP_PACKET_H