当前位置:网站首页>RTP 接发ps流工具改进(二)
RTP 接发ps流工具改进(二)
2022-07-02 22:44:00 【qianbo_insist】
RTP ps
上一次写了RTP工具发送RTP包,这次改进了发送和接收,真正能接收和发送图像,这次修改,使得RTP发送接收和PS流RTP发送接收都已经成功。延时在300毫秒左右。代码地址在上一篇的文章里面。
下面是接收,这次使用udp 异步接收,发送到解析线程解码显示,和主界面通信使用回调函数。里面也包含了存储h264的代码,每次500帧,这些以后都将使用配置进行,现在还不完善。
主要接收的改进在于使用了异步接收,同步接收依然保留,后面会做个开关去打开和关闭,发送和接收在界面上没有很好的做配置,以前是RTP 打包发送和接收,这次是PS流的打包发送和接收。读者暂时需要自己改动代码去使用。
UDPserver
这次使用的是boost的asio, 后面考虑单独使用c++20,和asio配合。
#pragma once
#include <cstdlib>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include "c_rtp.h"
#include "c_thread.h"
using namespace boost;
using boost::asio::ip::udp;
typedef void(*rtp_callback_data)(void* puser, void* pkt,int len, int w, int h, uint32_t ssrc);
typedef void(*rtp_callback_log)(void* puser, const char* log,...);
#define DEFINE_EC \ boost::system::error_code ec;
class IO_Thread;
class c_udpserver:public c_thread
{
//asio::strand<asio::io_context::executor_type> v_strand;
asio::io_context v_context;
asio::ip::udp::socket v_socket;
//ssrc rtpcontext
std::unordered_map<uint32_t, s_rtp_context*> v_ctxs;
s_rtp_context * getctx(uint32_t ssrc)
{
auto it = v_ctxs.find(ssrc);
if (it != v_ctxs.end())
return it->second;
else
{
s_rtp_context *sc = new s_rtp_context();
v_ctxs[ssrc] = sc;
return sc;
}
}
void data_call(s_rtp_context *ctx);
int live_rtp_unpack_h264(s_rtp_context *ctx, uint8_t *data, int inlen);
int live_rtp_unpack_ps(s_rtp_context *ctx,
uint8_t *data,
int inlen, uint32_t ssrc
);
public:
c_udpserver(short port):
//v_strand(io_context.get_executor()),
v_socket(v_context)
{
udp::endpoint ep(udp::v4(), port);
v_socket.open(ep.protocol());
v_socket.set_option(boost::asio::ip::udp::socket::reuse_address(true));
boost::asio::socket_base::receive_buffer_size recv_option(2*1024*1024);
v_socket.set_option(recv_option);
v_socket.bind(ep);
}
~c_udpserver()
{
//v_context_maps.clear();
}
void Run();
//to flv server
void do_receive_rtp_head();
void do_receive();
void set_callback(void *puser, rtp_callback_data cb, rtp_callback_log cblog)
{
v_callback_data = cb;
v_callback_log = cblog;
v_user = puser;
}
void do_send(std::size_t length);
void do_judge_spspps(s_rtp_context *ctx);
private:
udp::endpoint sender_endpoint_;
enum {
max_length = 1500};
char data_[max_length] = {
0};
public:
rtp_callback_data v_callback_data = NULL;
rtp_callback_log v_callback_log = NULL;
void* v_user = NULL;
public:
void Stop();
//给线程发送信息
void postmessage(uint32_t ssrc, int number);
void postmessage_2interface(char* strFmt, ...);
void postmessage_2show(void* pkt,int payload);
};
如代码所示,和界面通信主要是靠两个回调函数
rtp_callback_data v_callback_data = NULL;
rtp_callback_log v_callback_log = NULL;
其中v_user就是主界面,用空类型表示。
展示
为了不使用更多的库,先使用了GDI显示,里面也包含了SDL显示,读者可以自行修改。
class c_drawrgb24
{
public:
c_drawrgb24(void);
~c_drawrgb24(void);
protected:
void CreateDoubleBuffer(HDC hdc1, int cxClient1 ,int cyClient1,HDC hdc2,int cxClient2,int cyClient2);
public:
void Draw2(HWND hWnd,HWND hWnd2, unsigned char * buffer, int SrcW, int SrcH);
void DrawSDL(HWND hWnd, unsigned char * buffer, int SrcW, int SrcH);
//void DrawPInP(HWND hWnd
public:
//图像翻转
void SetVertial();
private:
LPBITMAPINFO m_lpBmpInfo;
bool m_bInit;
HBITMAP _hBm1;
HDC _hdc_buffer1;
HBITMAP _hBm2;
HDC _hdc_buffer2;
SDLDraw _sdldraw;
};
#ifdef _WIN32
#include <SDKDDKVer.h>
#endif
#include "c_drawrgb24.h"
c_drawrgb24::c_drawrgb24(void):
m_bInit(false),
m_lpBmpInfo(NULL),
_hBm1(NULL),
_hdc_buffer1(NULL),
_hBm2(NULL),
_hdc_buffer2(NULL)
{
}
c_drawrgb24::~c_drawrgb24(void)
{
if(m_lpBmpInfo)
delete m_lpBmpInfo;
}
void c_drawrgb24::SetVertial()
{
if(m_lpBmpInfo!=NULL)
m_lpBmpInfo->bmiHeader.biHeight = 0-m_lpBmpInfo->bmiHeader.biHeight;
}
void c_drawrgb24::CreateDoubleBuffer(HDC hdc1, int cxClient1 ,int cyClient1,HDC hdc2,int cxClient2,int cyClient2)
{
//创建虚拟位图
if(hdc1!=NULL)
{
_hBm1 = CreateCompatibleBitmap(hdc1,cxClient1,cyClient1);
//创建和hdc兼容的设备
_hdc_buffer1 = CreateCompatibleDC(hdc1);
SelectObject(_hdc_buffer1,_hBm1);
}
if(hdc2!=NULL)
{
_hBm2 = CreateCompatibleBitmap(hdc2,cxClient2,cyClient2);
//创建和hdc兼容的设备
_hdc_buffer1 = CreateCompatibleDC(hdc2);
SelectObject(_hdc_buffer2,_hBm2);
}
}
void c_drawrgb24::Draw2(HWND hWnd, HWND hWnd2,unsigned char * buffer, int SrcW, int SrcH)
{
HDC hDCDst1 = NULL;
HDC hDCDst2 = NULL;
RECT destRect1;
RECT destRect2;
if(hWnd!=NULL)
{
hDCDst1 = GetDC(hWnd);
GetClientRect(hWnd,&destRect1);
}
if(hWnd2!=NULL)
{
hDCDst2 = GetDC(hWnd2);
GetClientRect(hWnd2,&destRect2);
}
if(!m_bInit)
{
m_bInit = true;
m_lpBmpInfo=new BITMAPINFO;
m_lpBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_lpBmpInfo->bmiHeader.biWidth = SrcW;
m_lpBmpInfo->bmiHeader.biHeight= -SrcH;
m_lpBmpInfo->bmiHeader.biPlanes= 1;
m_lpBmpInfo->bmiHeader.biBitCount = 24;
m_lpBmpInfo->bmiHeader.biCompression = 0;
m_lpBmpInfo->bmiHeader.biSizeImage = 0;
m_lpBmpInfo->bmiHeader.biXPelsPerMeter = 0;
m_lpBmpInfo->bmiHeader.biYPelsPerMeter = 0;
m_lpBmpInfo->bmiHeader.biClrUsed=0;
m_lpBmpInfo->bmiHeader.biClrImportant = 0;
//CDC * dc = CDC::FromHandle(hDCDst);
//m_pMemDC = new CMemDC(*dc,DestRect);
}
if(hDCDst1!=NULL)
{
int DstWidth = destRect1.right-destRect1.left;
int DstHeight = destRect1.bottom- destRect1.top;
SetStretchBltMode(hDCDst1,STRETCH_HALFTONE);
::StretchDIBits(
//m_pMemDC->GetDC().GetSafeHdc(),
hDCDst1,
0, 0, DstWidth, DstHeight,
0, 0, SrcW, SrcH,
buffer, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY );
ReleaseDC(hWnd,hDCDst1);
}
if(hDCDst2!=NULL)
{
int DstWidth = destRect2.right-destRect2.left;
int DstHeight = destRect2.bottom- destRect2.top;
SetStretchBltMode(hDCDst2,STRETCH_HALFTONE);
::StretchDIBits(
//m_pMemDC->GetDC().GetSafeHdc(),
hDCDst2,
0, 0, DstWidth, DstHeight,
0, 0, SrcW, SrcH,
buffer, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY );
ReleaseDC(hWnd2,hDCDst2);
}
}
void c_drawrgb24::DrawSDL(HWND hWnd, unsigned char * buffer, int SrcW, int SrcH)
{
_sdldraw.draw_init(hWnd, SrcW, SrcH);
_sdldraw.draw(buffer, SrcW, SrcH);
}
新的代码已经提交,读者可以从我的第一篇文章中找到开源地址。
边栏推荐
- 可知论与熟能生巧
- Flexible combination of applications is a false proposition that has existed for 40 years
- C MVC creates a view to get rid of the influence of layout
- Pandora IOT development board learning (HAL Library) - Experiment 3 key input experiment (learning notes)
- 返回二叉树中最大的二叉搜索子树的大小
- @How to use bindsinstance in dagger2
- [OJ] intersection of two arrays (set, hash mapping...)
- Arduino - 字符判断函数
- 【STL源码剖析】仿函数(待补充)
- Three solutions to frequent sticking and no response of explorer in win11 system
猜你喜欢

Interface switching based on pyqt5 toolbar button -2

跨境电商如何通过打好数据底座,实现低成本稳步增长

Data set - fault diagnosis: various data and data description of bearings of Western Reserve University

CDN acceleration requires the domain name to be filed first

公司里只有一个测试是什么体验?听听他们怎么说吧

Yolox enhanced feature extraction network panet analysis

内网渗透 | 手把手教你如何进行内网渗透

MarkDown基本语法

Dishes launcher small green program and directory management (efficiency tool)

基于Pyqt5工具栏按钮可实现界面切换-2
随机推荐
接口自动化覆盖率统计——Jacoco使用
Go basic constant definition and use
[Verilog tutorial]
基于Pyqt5工具栏按钮可实现界面切换-1
第三方支付功能测试点【杭州多测师_王sir】【杭州多测师】
Win11系统explorer频繁卡死无响应的三种解决方法
ArrayList分析2 :Itr、ListIterator以及SubList中的坑
ArrayList analysis 2: pits in ITR, listiterator, and sublist
非路由组件之头部组件和底部组件书写
Container runtime analysis
Wechat applet basic learning (wxss)
Boost库链接错误解决方案
解决:exceptiole ‘xxxxx.QRTZ_LOCKS‘ doesn‘t exist以及mysql的my.cnf文件追加lower_case_table_names后启动报错
公司里只有一个测试是什么体验?听听他们怎么说吧
返回二叉树两个节点间的最大距离
MySQL Foundation
MarkDown基本语法
基于Pyqt5工具栏按钮可实现界面切换-2
Pandora IOT development board learning (HAL Library) - Experiment 3 key input experiment (learning notes)
附加:token;(没写完,别看…)