自学内容网 自学内容网

openRTP增加h265 发送

openRTP地址

openrtp 开源地址

选择h265 进行发送,h265 发送暂不支持ts
在这里插入图片描述

在这里插入图片描述

h265接收

打开sdp文件:打开目录下的testrtpvideoh265.sdp 文件,正常播放h265 的rtp 发送,接收器正在修正为ssdp协议发现,也暂时不支持h265 播放,OpenRTPServer代码并没有改变,计划增加h264 和 h265 的缓存播放,flv 格式存储

调试点

暂时只支持nvidia 英伟达显卡硬件编码的h265, libx265 出来的编码暂时不支持,使用debugview进行调试,写入文件test1.h265,打开文件正常
在这里插入图片描述
下面为接收存储的代码,简单存储,测试使用

#include <stdint.h>
#include <stdio.h>
#include <string>

static void SendMsgDbgview(const char* format, ...)
{
char buffer[1024];
strncpy(buffer, "RTP:", 4);
va_list args;
va_start(args, format);
vsnprintf(buffer + 4, sizeof(buffer) - 4, format, args);
va_end(args);
#ifdef _WIN32
#include <Windows.h>
OutputDebugStringA(buffer);
#else
int syslog_priority = LOG_INFO; 
syslog(syslog_priority, "%s", buffer);
#endif
}
class c_h26xStorage
{
FILE* v_fp = NULL;
int64_t v_num = 0;
uint32_t v_hash = 0;
std::string v_deviceurl;
uint32_t v_record_timestamp = 0;
int v_start = 0;
int v_end = 500;
public:

void Start(int end)
{
v_start = 0;
v_end = end;
char buffer[64];
sprintf(buffer, "./test1.h265");
if (v_fp != NULL)
fclose(v_fp);
v_fp = fopen(buffer, "wb");
}
void live_rtp_head(uint8_t* vps, int vlen, uint8_t* sps, int slen, uint8_t* pps, int plen)
{
if (v_fp == NULL)
return;
uint8_t prefix[4] = { 0x00,0x00,0x00,0x01 };
fwrite(&prefix[0], 4, 1, v_fp);
fwrite(vps, vlen, 1, v_fp);

fwrite(&prefix[0], 4, 1, v_fp);
fwrite(sps, slen, 1, v_fp);

fwrite(&prefix[0], 4, 1, v_fp);
fwrite(pps, plen, 1, v_fp);
}
void live_rtp_file(uint8_t* data, int len)
{
if (v_fp == NULL)
return;
if (data!=NULL && len > 0)
{
if (v_start < v_end)
{
fwrite(data, len, 1, v_fp);
}
SendMsgDbgview("this is the rtp write %d", v_start);
v_start++;
if (v_start == v_end)
{
fclose(v_fp);
v_fp = NULL;

SendMsgDbgview("the file is finish");
}

}
}
};

nvidia 编码

代码调试了一下以后,发现ffmpeg 使用libx265 编码出来的数据非常规,使用nvidia英伟达编码以后,跳过每帧的增强数据后正常播放,因为写了一个函数为AnalyseNalu_h265,同理AnalyseNalu_h264 在文件下也是有的,这边和编码和桌面编码使用h264不同,h265 使用global,vps,sps,pps在extradata 里面,使用libx265 软件编码的结果后面再进行调试修改。

void VideoEncoderThread::h265Cycle()
{
#define ON(x,y,p,k) \
listener_->OnCaptureVideoBuffer(x,y, p,k);

VideoEncoder  encoder;
uint8_t* extradata = NULL;
int extradatasize = 0;
encoder.Init_Global(v_format.width,v_format.height , v_format.width, v_format.height, 
v_format.videobitrate, v_format.fps, AV_CODEC_ID_H265, &extradata, extradatasize);
AVPacket* pkt = NULL;

uint8_t* vps, * sps, * pps, * se, * framestart;
int vpslen, spslen, ppslen, selen, framelen;
AnalyseNalu_h265(extradata, extradatasize, &vps, vpslen, &sps, spslen, &pps, ppslen, &se, selen, &framestart, framelen);


/*if (framestart != NULL)
ON(framestart, framelen, p, k);*/




float delay = 1000.0f / (float)(v_format.fps);
bool is_keyframe = true;
uint32_t start_timestamp = GetTimestamp32();
uint32_t start_clock = 0;
uint32_t tnow = start_timestamp;
int keycycyle = 0;

v_hsto.Start(500);
while (false == IsStop())
{
{
std::unique_lock<std::mutex> lock(v_mt);
pkt = encoder.EncodeFrameFromYUV420(v_yuvbuf);
}
if (pkt != NULL)
{

bool k = pkt->flags & AV_PKT_FLAG_KEY;
uint32_t p = (uint32_t)pkt->pts;

if (k == true)
{
if (vps != NULL)
ON(vps, vpslen, p, k);
if (sps != NULL)
ON(sps, spslen, p, k);
if (pps != NULL)
ON(pps, vpslen, p, k);
v_hsto.live_rtp_head(vps, vpslen, sps, spslen, pps, ppslen);
SendMsgDbgview("keyframe");
}
else
{
SendMsgDbgview("not keyframe");
}
uint8_t* vps1, *sps1, *pps1, *se1, * framestart1;
int vpslen1, spslen1, ppslen1, selen1, framelen1;
AnalyseNalu_h265(pkt->data, pkt->size, &vps1, vpslen1, &sps1, spslen1, &pps1, ppslen1, &se1, selen1, &framestart1, framelen1);

if (framestart1 != NULL)
{
ON(framestart1, framelen1, p, k);
v_hsto.live_rtp_file(framestart1, framelen1);
}
//ON(pkt->data, pkt->size, p, k);
}
tnow = GetTimestamp32();
uint32_t total = tnow - start_timestamp; //總共花費的時間
uint32_t fix_consume = (uint32_t)(++start_clock * delay);
if (total < fix_consume) {
int64_t diff = (int64_t)(fix_consume - total);
if (diff > 0) { //相差5毫秒以上
//cout << total << ":" << diff << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(diff));
}
}
is_keyframe = false;
if (keycycyle++ == v_format.fps)
{
is_keyframe = true;
keycycyle = 0;
}
}
}

原文地址:https://blog.csdn.net/qianbo042311/article/details/143660375

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!