RTP 接发ps流工具改进
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RTP 接发ps流工具改进相关的知识,希望对你有一定的参考价值。
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);
新的代码已经提交,读者可以从我的第一篇文章中找到开源地址。
以上是关于RTP 接发ps流工具改进的主要内容,如果未能解决你的问题,请参考以下文章