diff --git a/trunk/src/app/srs_app_rtc_sdp.cpp b/trunk/src/app/srs_app_rtc_sdp.cpp index 8f5e49a83..d87c5e097 100644 --- a/trunk/src/app/srs_app_rtc_sdp.cpp +++ b/trunk/src/app/srs_app_rtc_sdp.cpp @@ -1252,4 +1252,5 @@ srs_error_t SrsSdp::update_msid(string id) } return err; -} \ No newline at end of file +} + diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index ebfd088cb..676766e0b 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -483,6 +483,23 @@ void SrsRtcSource::init_for_play_before_publishing() video_track_desc->media_ = video_payload; 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()); @@ -1084,10 +1101,6 @@ srs_error_t SrsRtcRtpBuilder::on_video(SrsSharedPtrMessage* msg) if (has_idr) { SrsUniquePtr 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) { return srs_error_wrap(err, "package stap-a"); } @@ -1235,7 +1248,7 @@ srs_error_t SrsRtcRtpBuilder::package_stap_a(SrsSharedPtrMessage* msg, SrsRtpPac } memcpy(payload, (char*)param->data(), param->size()); - payload += (int)param->size(); + payload += (int)param->size(); } return err; @@ -1323,7 +1336,7 @@ srs_error_t SrsRtcRtpBuilder::package_nalus(SrsSharedPtrMessage* msg, const vect SrsRtpFUAPayloadHevc* fua = new SrsRtpFUAPayloadHevc(); if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { 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->start = bool(i == 0); @@ -1630,7 +1643,6 @@ srs_error_t SrsRtcFrameBuilder::packet_video(SrsRtpPacket* src) SrsRtpPacket* pkt = src->copy(); if (pkt->is_keyframe()) { - // TODO: 处理H265 return packet_video_key_frame(pkt); } diff --git a/trunk/src/app/srs_app_stream_bridge.cpp b/trunk/src/app/srs_app_stream_bridge.cpp index b10b08b2f..b80c49a69 100644 --- a/trunk/src/app/srs_app_stream_bridge.cpp +++ b/trunk/src/app/srs_app_stream_bridge.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include using namespace std; @@ -145,7 +144,7 @@ void SrsFrameToRtcBridge::on_unpublish() srs_error_t SrsFrameToRtcBridge::on_frame(SrsSharedPtrMessage* frame) { -#ifdef SRS_FFMPEG_FIT +#ifdef SRS_FFMPEG_FIT return rtp_builder_->on_frame(frame); #else return srs_success; @@ -157,25 +156,6 @@ srs_error_t SrsFrameToRtcBridge::on_rtp(SrsRtpPacket* 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 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 SrsCompositeBridge::SrsCompositeBridge() diff --git a/trunk/src/app/srs_app_stream_bridge.hpp b/trunk/src/app/srs_app_stream_bridge.hpp index aad045823..dfa4857c8 100644 --- a/trunk/src/app/srs_app_stream_bridge.hpp +++ b/trunk/src/app/srs_app_stream_bridge.hpp @@ -74,7 +74,6 @@ public: virtual void on_unpublish(); virtual srs_error_t on_frame(SrsSharedPtrMessage* frame); srs_error_t on_rtp(SrsRtpPacket* pkt); - srs_error_t update_codec(SrsVideoCodecId id); }; #endif diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 38e68211a..c92995024 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -676,7 +676,7 @@ srs_error_t SrsVideoFrame::add_sample(char* bytes, int size) // By default, use AVC(H.264) to parse NALU. // 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) { has_idr = true; @@ -751,12 +751,12 @@ srs_error_t SrsVideoFrame::parse_avc_b_frame(const SrsSample* sample, bool& is_b return err; } -srs_error_t SrsVideoFrame::parse_hevc_nalu_type(const SrsSample *sample, SrsHevcNaluType &hevc_nalu_type) +srs_error_t SrsVideoFrame::parse_hevc_nalu_type(const SrsSample* sample, SrsHevcNaluType& hevc_nalu_type) { srs_error_t err = srs_success; 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]; @@ -765,7 +765,7 @@ srs_error_t SrsVideoFrame::parse_hevc_nalu_type(const SrsSample *sample, SrsHevc return err; } -srs_error_t SrsVideoFrame::parse_hevc_b_frame(const SrsSample *sample, SrsFormat *format, bool &is_b_frame) +srs_error_t SrsVideoFrame::parse_hevc_b_frame(const SrsSample* sample, SrsFormat *format, bool& is_b_frame) { srs_error_t err = srs_success; @@ -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"); } - 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) { - bs.skip_bits(1); is_b_frame = false; return err; } + SrsUniquePtr 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; if ((err = bs.read_bits_ue(slice_pic_parameter_set_id)) != srs_success) { 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]); - uint8_t dependent_slice_segment_flag; + uint8_t dependent_slice_segment_flag = 0; if (!first_slice_segment_in_pic_flag) { if (pps->dependent_slice_segments_enabled_flag) { dependent_slice_segment_flag = bs.read_bit(); - } else { - dependent_slice_segment_flag = 0; } - } else { - dependent_slice_segment_flag = 0; } 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"); } - 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 @@ -2337,7 +2337,7 @@ srs_error_t SrsFormat::avc_demux_sps() // 7.4.1 NAL unit semantics // 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. - SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(nutv & 0x1f); + SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(nutv); if (nal_unit_type != 7) { return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_unit_type shall be equal to 7"); } diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index e461b0790..e1e19fa1c 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -502,6 +502,10 @@ enum SrsHevcNaluType { // @see https://datatracker.ietf.org/doc/html/rfc7798#section-1.1.4 #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 { SrsHevcSliceTypeB = 0, SrsHevcSliceTypeP = 1, diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 7f84dc5ee..791e069d1 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -33,9 +33,9 @@ const uint8_t kStapA = 24; const uint8_t kFuA = 28; // @see: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 -const uint8_t kStapHevc = 48; +const uint8_t kStapHevc = 48; // @see: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 -const uint8_t kFuHevc = 49; +const uint8_t kFuHevc = 49; // @see: https://tools.ietf.org/html/rfc6184#section-5.8 const uint8_t kStart = 0x80; // Fu-header start bit @@ -488,7 +488,7 @@ public: }; // 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 { public: @@ -511,7 +511,7 @@ public: }; // FU, for one NALU with multiple fragments. -// With only one payload. For HEVC. +// With only one payload for HEVC. class SrsRtpFUAPayloadHevc2 : public ISrsRtpPayloader { public: