1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Optimize init h265 track and format.

This commit is contained in:
chundonglinlin 2025-02-21 23:05:39 +08:00
parent 83e8877623
commit 8953dbfba1
7 changed files with 49 additions and 53 deletions

View file

@ -1253,3 +1253,4 @@ srs_error_t SrsSdp::update_msid(string id)
return err; return err;
} }

View file

@ -483,6 +483,23 @@ void SrsRtcSource::init_for_play_before_publishing()
video_track_desc->media_ = video_payload; video_track_desc->media_ = video_payload;
video_payload->set_h264_param_desc("level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f"); video_payload->set_h264_param_desc("level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f");
#ifdef SRS_H265
// default h265 video track description
SrsRtcTrackDescription* h265_video_track_desc = new SrsRtcTrackDescription();
stream_desc->video_track_descs_.push_back(h265_video_track_desc);
h265_video_track_desc->type_ = "video";
h265_video_track_desc->id_ = "video-" + srs_random_str(8);
h265_video_track_desc->ssrc_ = video_ssrc;
h265_video_track_desc->direction_ = "recvonly";
SrsVideoPayload* h265_video_payload = new SrsVideoPayload(kVideoPayloadType, "H265", kVideoSamplerate);
h265_video_track_desc->media_ = h265_video_payload;
h265_video_payload->set_h265_param_desc("level-id=180;profile-id=1;tier-flag=0;tx-mode=SRST");
#endif
} }
set_stream_desc(stream_desc.get()); set_stream_desc(stream_desc.get());
@ -1084,10 +1101,6 @@ srs_error_t SrsRtcRtpBuilder::on_video(SrsSharedPtrMessage* msg)
if (has_idr) { if (has_idr) {
SrsUniquePtr<SrsRtpPacket> pkt(new SrsRtpPacket()); SrsUniquePtr<SrsRtpPacket> pkt(new SrsRtpPacket());
if ((err = bridge_->update_codec(format->vcodec->id)) != srs_success) {
return srs_error_wrap(err, "update codec");
}
if ((err = package_stap_a(msg, pkt.get())) != srs_success) { if ((err = package_stap_a(msg, pkt.get())) != srs_success) {
return srs_error_wrap(err, "package stap-a"); return srs_error_wrap(err, "package stap-a");
} }
@ -1323,7 +1336,7 @@ srs_error_t SrsRtcRtpBuilder::package_nalus(SrsSharedPtrMessage* msg, const vect
SrsRtpFUAPayloadHevc* fua = new SrsRtpFUAPayloadHevc(); SrsRtpFUAPayloadHevc* fua = new SrsRtpFUAPayloadHevc();
if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) {
srs_freep(fua); srs_freep(fua);
return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); return srs_error_wrap(err, "read hevc samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes);
} }
fua->nalu_type = SrsHevcNaluTypeParse(header); fua->nalu_type = SrsHevcNaluTypeParse(header);
fua->start = bool(i == 0); fua->start = bool(i == 0);
@ -1630,7 +1643,6 @@ srs_error_t SrsRtcFrameBuilder::packet_video(SrsRtpPacket* src)
SrsRtpPacket* pkt = src->copy(); SrsRtpPacket* pkt = src->copy();
if (pkt->is_keyframe()) { if (pkt->is_keyframe()) {
// TODO: 处理H265
return packet_video_key_frame(pkt); return packet_video_key_frame(pkt);
} }

View file

@ -13,7 +13,6 @@
#include <srs_protocol_rtmp_stack.hpp> #include <srs_protocol_rtmp_stack.hpp>
#include <srs_kernel_rtc_rtp.hpp> #include <srs_kernel_rtc_rtp.hpp>
#include <srs_core_autofree.hpp> #include <srs_core_autofree.hpp>
#include <srs_protocol_utility.hpp>
#include <vector> #include <vector>
using namespace std; using namespace std;
@ -157,25 +156,6 @@ srs_error_t SrsFrameToRtcBridge::on_rtp(SrsRtpPacket* pkt)
return source_->on_rtp(pkt); return source_->on_rtp(pkt);
} }
srs_error_t SrsFrameToRtcBridge::update_codec(SrsVideoCodecId id)
{
// init with H264 default, so we need check if it's H265 only.
if (id == SrsVideoCodecIdHEVC) {
if (source_->get_track_desc("video", "H265").empty()) {
std::vector<SrsRtcTrackDescription*> video_track_descs = source_->get_track_desc("video", "H264");
if (!video_track_descs.empty()) {
SrsRtcTrackDescription* video_track_desc = video_track_descs.at(0);
SrsVideoPayload* video_payload = (SrsVideoPayload*)video_track_desc->media_;
video_payload->name_ = "H265";
video_payload->set_h265_param_desc("level-id=180;profile-id=1;tier-flag=0;tx-mode=SRST");
srs_trace("RTC: Switch video codec %d(%s) to %d(%s)", SrsVideoCodecIdAVC, srs_video_codec_id2str(SrsVideoCodecIdAVC).c_str(),
id, srs_video_codec_id2str(id).c_str());
}
}
}
return srs_success;
}
#endif #endif
SrsCompositeBridge::SrsCompositeBridge() SrsCompositeBridge::SrsCompositeBridge()

View file

@ -74,7 +74,6 @@ public:
virtual void on_unpublish(); virtual void on_unpublish();
virtual srs_error_t on_frame(SrsSharedPtrMessage* frame); virtual srs_error_t on_frame(SrsSharedPtrMessage* frame);
srs_error_t on_rtp(SrsRtpPacket* pkt); srs_error_t on_rtp(SrsRtpPacket* pkt);
srs_error_t update_codec(SrsVideoCodecId id);
}; };
#endif #endif

View file

@ -676,7 +676,7 @@ srs_error_t SrsVideoFrame::add_sample(char* bytes, int size)
// By default, use AVC(H.264) to parse NALU. // By default, use AVC(H.264) to parse NALU.
// For video, parse the nalu type, set the IDR flag. // For video, parse the nalu type, set the IDR flag.
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(bytes[0] & 0x1f); SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(bytes[0]);
if (nal_unit_type == SrsAvcNaluTypeIDR) { if (nal_unit_type == SrsAvcNaluTypeIDR) {
has_idr = true; has_idr = true;
@ -756,7 +756,7 @@ srs_error_t SrsVideoFrame::parse_hevc_nalu_type(const SrsSample *sample, SrsHevc
srs_error_t err = srs_success; srs_error_t err = srs_success;
if (sample == NULL || sample->size < 1) { if (sample == NULL || sample->size < 1) {
return srs_error_new(ERROR_NALU_EMPTY, "empty nalu"); return srs_error_new(ERROR_NALU_EMPTY, "empty hevc nalu");
} }
uint8_t header = sample->bytes[0]; uint8_t header = sample->bytes[0];
@ -774,19 +774,20 @@ srs_error_t SrsVideoFrame::parse_hevc_b_frame(const SrsSample *sample, SrsFormat
return srs_error_wrap(err, "parse hevc nalu type error"); return srs_error_wrap(err, "parse hevc nalu type error");
} }
SrsBuffer stream(sample->bytes, sample->size);
stream.skip(2);
// @see 7.3.6.1 General slice segment header syntax
// @doc ITU-T-H.265-2021.pdf, page 66.
SrsBitBuffer bs(&stream);
uint8_t first_slice_segment_in_pic_flag = bs.read_bit();
if (nalu_type > SrsHevcNaluType_CODED_SLICE_BLA && nalu_type < SrsHevcNaluType_RESERVED_23) { if (nalu_type > SrsHevcNaluType_CODED_SLICE_BLA && nalu_type < SrsHevcNaluType_RESERVED_23) {
bs.skip_bits(1);
is_b_frame = false; is_b_frame = false;
return err; return err;
} }
SrsUniquePtr<SrsBuffer> stream(new SrsBuffer(sample->bytes, sample->size));
stream->skip(2);
// @see 7.3.6.1 General slice segment header syntax
// @doc ITU-T-H.265-2021.pdf, page 66.
SrsBitBuffer bs(stream.get());
uint8_t first_slice_segment_in_pic_flag = bs.read_bit();
uint32_t slice_pic_parameter_set_id; uint32_t slice_pic_parameter_set_id;
if ((err = bs.read_bits_ue(slice_pic_parameter_set_id)) != srs_success) { if ((err = bs.read_bits_ue(slice_pic_parameter_set_id)) != srs_success) {
return srs_error_wrap(err, "read slice pic parameter set id"); return srs_error_wrap(err, "read slice pic parameter set id");
@ -798,15 +799,11 @@ srs_error_t SrsVideoFrame::parse_hevc_b_frame(const SrsSample *sample, SrsFormat
SrsHevcRbspPps *pps = &(format->vcodec->hevc_dec_conf_record_.pps_table[slice_pic_parameter_set_id]); SrsHevcRbspPps *pps = &(format->vcodec->hevc_dec_conf_record_.pps_table[slice_pic_parameter_set_id]);
uint8_t dependent_slice_segment_flag; uint8_t dependent_slice_segment_flag = 0;
if (!first_slice_segment_in_pic_flag) { if (!first_slice_segment_in_pic_flag) {
if (pps->dependent_slice_segments_enabled_flag) { if (pps->dependent_slice_segments_enabled_flag) {
dependent_slice_segment_flag = bs.read_bit(); dependent_slice_segment_flag = bs.read_bit();
} else {
dependent_slice_segment_flag = 0;
} }
} else {
dependent_slice_segment_flag = 0;
} }
if (dependent_slice_segment_flag) { if (dependent_slice_segment_flag) {
@ -822,7 +819,10 @@ srs_error_t SrsVideoFrame::parse_hevc_b_frame(const SrsSample *sample, SrsFormat
return srs_error_wrap(err, "read slice type"); return srs_error_wrap(err, "read slice type");
} }
is_b_frame = (slice_type == SrsHevcSliceTypeB) ? true : false; is_b_frame = slice_type == SrsHevcSliceTypeB;
if (is_b_frame) {
srs_verbose("nalu_type=%d, slice type=%d", nalu_type, slice_type);
}
// no need to evaluate the rest // no need to evaluate the rest
@ -2337,7 +2337,7 @@ srs_error_t SrsFormat::avc_demux_sps()
// 7.4.1 NAL unit semantics // 7.4.1 NAL unit semantics
// ISO_IEC_14496-10-AVC-2012.pdf, page 61. // ISO_IEC_14496-10-AVC-2012.pdf, page 61.
// nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1. // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(nutv & 0x1f); SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(nutv);
if (nal_unit_type != 7) { if (nal_unit_type != 7) {
return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_unit_type shall be equal to 7"); return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_unit_type shall be equal to 7");
} }

View file

@ -502,6 +502,10 @@ enum SrsHevcNaluType {
// @see https://datatracker.ietf.org/doc/html/rfc7798#section-1.1.4 // @see https://datatracker.ietf.org/doc/html/rfc7798#section-1.1.4
#define SrsHevcNaluTypeParse(code) (SrsHevcNaluType)((code & 0x7E) >> 1) #define SrsHevcNaluTypeParse(code) (SrsHevcNaluType)((code & 0x7E) >> 1)
/**
* @see Table 7-7 Name association to slice_type
* @doc ITU-T-H.265-2021.pdf, page 96.
*/
enum SrsHevcSliceType { enum SrsHevcSliceType {
SrsHevcSliceTypeB = 0, SrsHevcSliceTypeB = 0,
SrsHevcSliceTypeP = 1, SrsHevcSliceTypeP = 1,

View file

@ -488,7 +488,7 @@ public:
}; };
// FU, for one NALU with multiple fragments. // FU, for one NALU with multiple fragments.
// With more than one payload. For HEVC. // With more than one payload for HEVC.
class SrsRtpFUAPayloadHevc : public ISrsRtpPayloader class SrsRtpFUAPayloadHevc : public ISrsRtpPayloader
{ {
public: public:
@ -511,7 +511,7 @@ public:
}; };
// FU, for one NALU with multiple fragments. // FU, for one NALU with multiple fragments.
// With only one payload. For HEVC. // With only one payload for HEVC.
class SrsRtpFUAPayloadHevc2 : public ISrsRtpPayloader class SrsRtpFUAPayloadHevc2 : public ISrsRtpPayloader
{ {
public: public: