diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 676766e0b..62dd000d7 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -483,23 +483,6 @@ 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()); @@ -1090,6 +1073,20 @@ srs_error_t SrsRtcRtpBuilder::on_video(SrsSharedPtrMessage* msg) return err; } + // support video codec: h264/h265 + SrsVideoCodecId vcodec = format->vcodec->id; + if (vcodec != SrsVideoCodecIdAVC && vcodec != SrsVideoCodecIdHEVC) { + return err; + } + +#ifdef SRS_H265 + if (vcodec == SrsVideoCodecIdHEVC) { + if ((err = bridge_->update_codec(vcodec)) != srs_success) { + return srs_error_wrap(err, "update codec"); + } + } +#endif + bool has_idr = false; vector samples; if ((err = filter(msg, format, has_idr, samples)) != srs_success) { diff --git a/trunk/src/app/srs_app_stream_bridge.cpp b/trunk/src/app/srs_app_stream_bridge.cpp index b80c49a69..e45d75f13 100644 --- a/trunk/src/app/srs_app_stream_bridge.cpp +++ b/trunk/src/app/srs_app_stream_bridge.cpp @@ -95,6 +95,8 @@ SrsFrameToRtcBridge::SrsFrameToRtcBridge(SrsSharedPtr source) rtp_builder_ = new SrsRtcRtpBuilder(this, audio_ssrc, audio_payload_type, video_ssrc, video_payload_type); #endif + + codec_switched_ = false; } SrsFrameToRtcBridge::~SrsFrameToRtcBridge() @@ -156,6 +158,44 @@ srs_error_t SrsFrameToRtcBridge::on_rtp(SrsRtpPacket* pkt) return source_->on_rtp(pkt); } +srs_error_t SrsFrameToRtcBridge::update_codec(SrsVideoCodecId id) +{ + srs_error_t err = srs_success; + + // Only handle H.265/HEVC codec switch. + if (id != SrsVideoCodecIdHEVC) { + return err; + } + + if (codec_switched_) { + return err; + } + + // Check if H.265 track description exists + if (!source_->get_track_desc("video", "H265").empty()) { + return err; + } + + // Try to convert H.264 track to H.265 + std::vector video_track_descs = source_->get_track_desc("video", "H264"); + if (video_track_descs.empty()) { + return srs_error_new(ERROR_RTC_NO_TRACK, "no H264 track found for conversion"); + } + + 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"); + + codec_switched_ = true; + + 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 err; +} + #endif SrsCompositeBridge::SrsCompositeBridge() diff --git a/trunk/src/app/srs_app_stream_bridge.hpp b/trunk/src/app/srs_app_stream_bridge.hpp index dfa4857c8..531091252 100644 --- a/trunk/src/app/srs_app_stream_bridge.hpp +++ b/trunk/src/app/srs_app_stream_bridge.hpp @@ -65,6 +65,8 @@ private: #if defined(SRS_FFMPEG_FIT) SrsRtcRtpBuilder* rtp_builder_; #endif +private: + bool codec_switched_; public: SrsFrameToRtcBridge(SrsSharedPtr source); virtual ~SrsFrameToRtcBridge(); @@ -74,6 +76,7 @@ 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