Refactor code for #4349 for better review. (#4405)

Also for augment AI to review it.
This commit is contained in:
Winlin 2025-06-27 10:52:00 -04:00 committed by GitHub
parent 40df358e50
commit 07163df9a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 108 additions and 72 deletions

View File

@ -1680,50 +1680,9 @@ srs_error_t SrsRtcFrameBuilder::packet_video_key_frame(SrsRtpPacket* pkt)
{
srs_error_t err = srs_success;
// For OBS WHIP, it uses RTP Raw packet with SPS/PPS/IDR frame. Note that not all
// raw payload is SPS/PPS.
bool has_sps_pps_in_raw_payload = false;
SrsRtpRawPayload* raw_payload = dynamic_cast<SrsRtpRawPayload*>(pkt->payload());
if (raw_payload) {
if (pkt->nalu_type == SrsAvcNaluTypeSPS) {
has_sps_pps_in_raw_payload = true;
srs_freep(obs_whip_sps_);
obs_whip_sps_ = pkt->copy();
} else if (pkt->nalu_type == SrsAvcNaluTypePPS) {
has_sps_pps_in_raw_payload = true;
srs_freep(obs_whip_pps_);
obs_whip_pps_ = pkt->copy();
}
// Ignore if one of OBS WHIP SPS/PPS is not ready.
if (has_sps_pps_in_raw_payload && (!obs_whip_sps_ || !obs_whip_pps_)) {
return err;
}
}
// Generally, there will be SPS+PPS+IDR in a STAP-A packet.
SrsRtpSTAPPayload* stap_payload = dynamic_cast<SrsRtpSTAPPayload*>(pkt->payload());
// Handle SPS/PPS in cache or STAP-A packet.
if (stap_payload || has_sps_pps_in_raw_payload) {
// Get the SPS/PPS from cache or STAP-A packet.
SrsSample* sps = stap_payload ? stap_payload->get_sps() : NULL;
if (!sps && obs_whip_sps_) sps = dynamic_cast<SrsRtpRawPayload*>(obs_whip_sps_->payload())->sample_;
SrsSample* pps = stap_payload ? stap_payload->get_pps() : NULL;
if (!pps && obs_whip_pps_) pps = dynamic_cast<SrsRtpRawPayload*>(obs_whip_pps_->payload())->sample_;
if (!sps || !pps) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "no sps or pps in stap-a rtp. sps: %p, pps:%p", sps, pps);
}
// Packet SPS/PPS to RTMP keyframe.
err = packet_sps_pps(pkt, sps, pps);
// Always reset the SPS/PPS cache after used it.
srs_freep(obs_whip_sps_);
srs_freep(obs_whip_pps_);
if (err != srs_success) {
return srs_error_wrap(err, "packet sps/pps");
}
err = packet_sequence_header_avc(pkt);
if (err != srs_success) {
return srs_error_wrap(err, "packet video key frame");
}
if (-1 == rtp_key_frame_ts_) {
@ -1779,7 +1738,60 @@ srs_error_t SrsRtcFrameBuilder::packet_video_key_frame(SrsRtpPacket* pkt)
return err;
}
srs_error_t SrsRtcFrameBuilder::packet_sps_pps(SrsRtpPacket* pkt, SrsSample* sps, SrsSample* pps)
srs_error_t SrsRtcFrameBuilder::packet_sequence_header_avc(SrsRtpPacket* pkt)
{
srs_error_t err = srs_success;
// For OBS WHIP, it uses RTP Raw packet with SPS/PPS/IDR frame. Note that not all
// raw payload is SPS/PPS.
bool has_sps_pps_in_raw_payload = false;
SrsRtpRawPayload* raw_payload = dynamic_cast<SrsRtpRawPayload*>(pkt->payload());
if (raw_payload) {
if (pkt->nalu_type == SrsAvcNaluTypeSPS) {
has_sps_pps_in_raw_payload = true;
srs_freep(obs_whip_sps_);
obs_whip_sps_ = pkt->copy();
} else if (pkt->nalu_type == SrsAvcNaluTypePPS) {
has_sps_pps_in_raw_payload = true;
srs_freep(obs_whip_pps_);
obs_whip_pps_ = pkt->copy();
}
// Ignore if one of OBS WHIP SPS/PPS is not ready.
if (has_sps_pps_in_raw_payload && (!obs_whip_sps_ || !obs_whip_pps_)) {
return err;
}
}
// Generally, there will be SPS+PPS+IDR in a STAP-A packet.
SrsRtpSTAPPayload* stap_payload = dynamic_cast<SrsRtpSTAPPayload*>(pkt->payload());
// Handle SPS/PPS in cache or STAP-A packet.
if (stap_payload || has_sps_pps_in_raw_payload) {
// Get the SPS/PPS from cache or STAP-A packet.
SrsSample* sps = stap_payload ? stap_payload->get_sps() : NULL;
if (!sps && obs_whip_sps_) sps = dynamic_cast<SrsRtpRawPayload*>(obs_whip_sps_->payload())->sample_;
SrsSample* pps = stap_payload ? stap_payload->get_pps() : NULL;
if (!pps && obs_whip_pps_) pps = dynamic_cast<SrsRtpRawPayload*>(obs_whip_pps_->payload())->sample_;
if (!sps || !pps) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "no sps or pps in stap-a rtp. sps: %p, pps:%p", sps, pps);
}
// Packet SPS/PPS to RTMP keyframe.
err = do_packet_sequence_header_avc(pkt, sps, pps);
// Always reset the SPS/PPS cache after used it.
srs_freep(obs_whip_sps_);
srs_freep(obs_whip_pps_);
if (err != srs_success) {
return srs_error_wrap(err, "packet sps/pps");
}
}
return err;
}
srs_error_t SrsRtcFrameBuilder::do_packet_sequence_header_avc(SrsRtpPacket* pkt, SrsSample* sps, SrsSample* pps)
{
srs_error_t err = srs_success;

View File

@ -356,7 +356,8 @@ private:
private:
srs_error_t packet_video(SrsRtpPacket* pkt);
srs_error_t packet_video_key_frame(SrsRtpPacket* pkt);
srs_error_t packet_sps_pps(SrsRtpPacket* pkt, SrsSample* sps, SrsSample* pps);
srs_error_t packet_sequence_header_avc(SrsRtpPacket* pkt);
srs_error_t do_packet_sequence_header_avc(SrsRtpPacket* pkt, SrsSample* sps, SrsSample* pps);
private:
inline uint16_t cache_index(uint16_t current_sn) {
return current_sn % s_cache_size;

View File

@ -946,21 +946,16 @@ srs_error_t SrsRtpPacket::decode(SrsBuffer* buf)
return err;
}
bool SrsRtpPacket::is_keyframe()
// Helper function to check if H.264 RTP packet is a keyframe
bool srs_rtp_packet_h264_is_keyframe(uint8_t nalu_type, ISrsRtpPayloader* payload)
{
// False if audio packet
if(SrsFrameTypeAudio == frame_type) {
return false;
}
// It's normal H264 video rtp packet
if (nalu_type == kStapA) {
SrsRtpSTAPPayload* stap_payload = dynamic_cast<SrsRtpSTAPPayload*>(payload_);
SrsRtpSTAPPayload* stap_payload = dynamic_cast<SrsRtpSTAPPayload*>(payload);
if(NULL != stap_payload->get_sps() || NULL != stap_payload->get_pps()) {
return true;
}
} else if (nalu_type == kFuA) {
SrsRtpFUAPayload2* fua_payload = dynamic_cast<SrsRtpFUAPayload2*>(payload_);
SrsRtpFUAPayload2* fua_payload = dynamic_cast<SrsRtpFUAPayload2*>(payload);
if(SrsAvcNaluTypeIDR == fua_payload->nalu_type) {
return true;
}
@ -968,28 +963,56 @@ bool SrsRtpPacket::is_keyframe()
if((SrsAvcNaluTypeIDR == nalu_type) || (SrsAvcNaluTypeSPS == nalu_type) || (SrsAvcNaluTypePPS == nalu_type)) {
return true;
}
#ifdef SRS_H265
if(nalu_type == kStapHevc) {
SrsRtpSTAPPayloadHevc* stap_payload = dynamic_cast<SrsRtpSTAPPayloadHevc*>(payload_);
if(NULL != stap_payload->get_vps() || NULL != stap_payload->get_sps() || NULL != stap_payload->get_pps()) {
return true;
}
} else if(nalu_type == kFuHevc) {
SrsRtpFUAPayloadHevc2* fua_payload = dynamic_cast<SrsRtpFUAPayloadHevc2*>(payload_);
if(fua_payload->nalu_type >= SrsHevcNaluType_CODED_SLICE_BLA && fua_payload->nalu_type <= SrsHevcNaluType_RESERVED_23) {
return true;
}
} else {
if((SrsHevcNaluType_VPS == nalu_type) || (SrsHevcNaluType_SPS == nalu_type) || (SrsHevcNaluType_PPS == nalu_type)) {
return true;
}
}
#endif
}
return false;
}
#ifdef SRS_H265
// Helper function to check if H.265 RTP packet is a keyframe
bool srs_rtp_packet_h265_is_keyframe(uint8_t nalu_type, ISrsRtpPayloader* payload)
{
if(nalu_type == kStapHevc) {
SrsRtpSTAPPayloadHevc* stap_payload = dynamic_cast<SrsRtpSTAPPayloadHevc*>(payload);
if(NULL != stap_payload->get_vps() || NULL != stap_payload->get_sps() || NULL != stap_payload->get_pps()) {
return true;
}
} else if(nalu_type == kFuHevc) {
SrsRtpFUAPayloadHevc2* fua_payload = dynamic_cast<SrsRtpFUAPayloadHevc2*>(payload);
if(fua_payload->nalu_type >= SrsHevcNaluType_CODED_SLICE_BLA && fua_payload->nalu_type <= SrsHevcNaluType_RESERVED_23) {
return true;
}
} else {
if((SrsHevcNaluType_VPS == nalu_type) || (SrsHevcNaluType_SPS == nalu_type) || (SrsHevcNaluType_PPS == nalu_type)) {
return true;
}
}
return false;
}
#endif
bool SrsRtpPacket::is_keyframe()
{
// False if audio packet
if(SrsFrameTypeAudio == frame_type) {
return false;
}
// Check H.264 keyframe types
if (nalu_type == kStapA || nalu_type == kFuA ||
nalu_type == SrsAvcNaluTypeIDR || nalu_type == SrsAvcNaluTypeSPS || nalu_type == SrsAvcNaluTypePPS) {
return srs_rtp_packet_h264_is_keyframe(nalu_type, payload_);
}
#ifdef SRS_H265
// Check H.265 keyframe types
return srs_rtp_packet_h265_is_keyframe(nalu_type, payload_);
#else
return false;
#endif
}
SrsRtpRawPayload::SrsRtpRawPayload()
{
payload = NULL;