live555 RTSP流媒体服务器如何修改SDK中的sps/pps/vps为可选项

在使用live555做为转发服务器, 在处理客户端请求时, 有时前端的流还没过来,而又需要及时的回复客户端,在live555官方代码中,如果不填写vps(H.265)&sps&pps的话,是直接返回失败的, 所以需要对该流程做修改, 以保证和客户端的正常交互;

分析问题

找到生成sdp信息的位置,修改其中的逻辑;

解决问题

详见以下灰色背景中的代码:
char const* H264VideoRTPSink::auxSDPLine() {
// Generate a new “a=fmtp:” line each time, using our SPS and PPS (if we have them),
// otherwise parameters from our framer source (in case they’ve changed since the last time that
// we were called):
H264or5VideoStreamFramer* framerSource = NULL;
u_int8_t* vpsDummy = NULL; unsigned vpsDummySize = 0;
u_int8_t* sps = fSPS; unsigned spsSize = fSPSSize;
u_int8_t* pps = fPPS; unsigned ppsSize = fPPSSize;
if (sps == NULL || pps == NULL) {
// We need to get SPS and PPS from our framer source:
if (fOurFragmenter == NULL) return NULL; // we don’t yet have a fragmenter (and therefore not a source)
framerSource = (H264or5VideoStreamFramer*)(fOurFragmenter->inputSource());
if (framerSource == NULL) return NULL; // we don’t yet have a source

framerSource->getVPSandSPSandPPS(vpsDummy, vpsDummySize, sps, spsSize, pps, ppsSize);
if (sps == NULL || pps == NULL)
{

#if 1
//add by gavin
char const* fmtpFmt =
“a=fmtp:%d packetization-mode=1”
//";profile-level-id=%06X"
“;sprop-parameter-sets=\r\n”;
unsigned fmtpFmtSize = (unsigned)strlen(fmtpFmt)
+ 3 /* max char len /
+ 6 /
3 bytes in hex /
+ 0;
char
fmtp = new char[fmtpFmtSize];
memset(fmtp, 0x00, fmtpFmtSize);
sprintf(fmtp, fmtpFmt,
rtpPayloadType());

  delete[] fFmtpSDPLine; fFmtpSDPLine = fmtp;
  return fFmtpSDPLine;

#endif

	return NULL; // our source isn't ready
}

}

// Set up the “a=fmtp:” SDP line for this stream:
u_int8_t* spsWEB = new u_int8_t[spsSize]; // “WEB” means “Without Emulation Bytes”
unsigned spsWEBSize = removeH264or5EmulationBytes(spsWEB, spsSize, sps, spsSize);
if (spsWEBSize < 4) { // Bad SPS size => assume our source isn’t ready
delete[] spsWEB;
return NULL;
}
u_int32_t profileLevelId = (spsWEB[1]<<16) | (spsWEB[2]<<8) | spsWEB[3];
delete[] spsWEB;

char* sps_base64 = base64Encode((char*)sps, spsSize);
char* pps_base64 = base64Encode((char*)pps, ppsSize);

char const* fmtpFmt =
“a=fmtp:%d packetization-mode=1”
“;profile-level-id=%06X”
“;sprop-parameter-sets=%s,%s\r\n”;
unsigned fmtpFmtSize = (unsigned)strlen(fmtpFmt)
+ 3 /* max char len /
+ 6 /
3 bytes in hex /
+ (unsigned)strlen(sps_base64) + (unsigned)strlen(pps_base64);
char
fmtp = new char[fmtpFmtSize];
sprintf(fmtp, fmtpFmt,
rtpPayloadType(),
profileLevelId,
sps_base64, pps_base64);

delete[] sps_base64;
delete[] pps_base64;

delete[] fFmtpSDPLine; fFmtpSDPLine = fmtp;
return fFmtpSDPLine;
}

char const* H265VideoRTPSink::auxSDPLine() {
// Generate a new “a=fmtp:” line each time, using our VPS, SPS and PPS (if we have them),
// otherwise parameters from our framer source (in case they’ve changed since the last time that
// we were called):
H264or5VideoStreamFramer* framerSource = NULL;
u_int8_t* vps = fVPS; unsigned vpsSize = fVPSSize;
u_int8_t* sps = fSPS; unsigned spsSize = fSPSSize;
u_int8_t* pps = fPPS; unsigned ppsSize = fPPSSize;
if (vps == NULL || sps == NULL || pps == NULL) {
// We need to get VPS, SPS and PPS from our framer source:
if (fOurFragmenter == NULL) return NULL; // we don’t yet have a fragmenter (and therefore not a source)
framerSource = (H264or5VideoStreamFramer*)(fOurFragmenter->inputSource());
if (framerSource == NULL) return NULL; // we don’t yet have a source

framerSource->getVPSandSPSandPPS(vps, vpsSize, sps, spsSize, pps, ppsSize);
if (vps == NULL || sps == NULL || pps == NULL) {

	//add by gavin
  char const* fmtpFmt =
	"a=fmtp:%d packetization-mode=1"
	//";profile-level-id=%06X"
	";sprop-vps=; sprop-sps=; sprop-pps=\r\n";
  unsigned fmtpFmtSize = (unsigned)strlen(fmtpFmt)
	+ 3 /* max char len */
	+ 6 /* 3 bytes in hex */
	+ 0;
  char* fmtp = new char[fmtpFmtSize];
  memset(fmtp, 0x00, fmtpFmtSize);
  sprintf(fmtp, fmtpFmt,
		  rtpPayloadType());

  delete[] fFmtpSDPLine; fFmtpSDPLine = fmtp;
  return fFmtpSDPLine;


  return NULL; // our source isn't ready
}

}

// Set up the “a=fmtp:” SDP line for this stream.
u_int8_t* vpsWEB = new u_int8_t[vpsSize]; // “WEB” means “Without Emulation Bytes”
unsigned vpsWEBSize = removeH264or5EmulationBytes(vpsWEB, vpsSize, vps, vpsSize);
if (vpsWEBSize < 6/‘profile_tier_level’ offset/ + 12/num ‘profile_tier_level’ bytes/) {
// Bad VPS size => assume our source isn’t ready
delete[] vpsWEB;
return NULL;
}
u_int8_t const* profileTierLevelHeaderBytes = &vpsWEB[6];
unsigned profileSpace = profileTierLevelHeaderBytes[0]>>6; // general_profile_space
unsigned profileId = profileTierLevelHeaderBytes[0]&0x1F; // general_profile_idc
unsigned tierFlag = (profileTierLevelHeaderBytes[0]>>5)&0x1; // general_tier_flag
unsigned levelId = profileTierLevelHeaderBytes[11]; // general_level_idc
u_int8_t const* interop_constraints = &profileTierLevelHeaderBytes[5];
char interopConstraintsStr[100];
sprintf(interopConstraintsStr, “%02X%02X%02X%02X%02X%02X”,
interop_constraints[0], interop_constraints[1], interop_constraints[2],
interop_constraints[3], interop_constraints[4], interop_constraints[5]);
delete[] vpsWEB;

char* sprop_vps = base64Encode((char*)vps, vpsSize);
char* sprop_sps = base64Encode((char*)sps, spsSize);
char* sprop_pps = base64Encode((char*)pps, ppsSize);

char const* fmtpFmt =
“a=fmtp:%d profile-space=%u”
“;profile-id=%u”
“;tier-flag=%u”
“;level-id=%u”
“;interop-constraints=%s”
“;sprop-vps=%s”
“;sprop-sps=%s”
“;sprop-pps=%s\r\n”;
unsigned fmtpFmtSize = (unsigned)strlen(fmtpFmt)
+ 3 /* max num chars: rtpPayloadType / + 20 / max num chars: profile_space /
+ 20 /
max num chars: profile_id /
+ 20 /
max num chars: tier_flag /
+ 20 /
max num chars: level_id /
+ (unsigned)strlen(interopConstraintsStr)
+ (unsigned)strlen(sprop_vps)
+ (unsigned)strlen(sprop_sps)
+ (unsigned)strlen(sprop_pps);
char
fmtp = new char[fmtpFmtSize];
sprintf(fmtp, fmtpFmt,
rtpPayloadType(), profileSpace,
profileId,
tierFlag,
levelId,
interopConstraintsStr,
sprop_vps,
sprop_sps,
sprop_pps);

delete[] sprop_vps;
delete[] sprop_sps;
delete[] sprop_pps;

delete[] fFmtpSDPLine; fFmtpSDPLine = fmtp;
return fFmtpSDPLine;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值