From aad9b3bf6826e4569da8fae410ebc3380b3ab950 Mon Sep 17 00:00:00 2001 From: sladro Date: Mon, 5 Jan 2026 16:18:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AEbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/input_rtsp/input_rtsp_node.cpp | 70 ++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/plugins/input_rtsp/input_rtsp_node.cpp b/plugins/input_rtsp/input_rtsp_node.cpp index b3391e8..9a0337d 100644 --- a/plugins/input_rtsp/input_rtsp_node.cpp +++ b/plugins/input_rtsp/input_rtsp_node.cpp @@ -20,6 +20,7 @@ extern "C" { #ifdef RK3588_ENABLE_FFMPEG extern "C" { +#include #include #include #include @@ -310,6 +311,14 @@ private: #endif #if defined(RK3588_ENABLE_FFMPEG) && defined(RK3588_ENABLE_MPP) + static bool IsAnnexB(const uint8_t* data, size_t size) { + if (!data || size < 4) return false; + // 00 00 01 or 00 00 00 01 + if (data[0] == 0 && data[1] == 0 && data[2] == 1) return true; + if (data[0] == 0 && data[1] == 0 && data[2] == 0 && data[3] == 1) return true; + return false; + } + struct MppDecoderWrapper { ~MppDecoderWrapper() { Shutdown(); } @@ -358,6 +367,7 @@ private: mpp_packet_set_pos(packet, pkt_data); mpp_packet_set_length(packet, size); mpp_packet_set_pts(packet, pts_us); + mpp_packet_clr_eos(packet); if (eos) mpp_packet_set_eos(packet); bool pkt_done = false; @@ -393,8 +403,6 @@ private: break; } - mpp_packet_deinit(&packet); - packet = nullptr; return true; } @@ -430,14 +438,18 @@ private: while (running_.load()) { AVFormatContext* fmt_ctx = nullptr; AVPacket* pkt = av_packet_alloc(); + AVPacket* filt_pkt = av_packet_alloc(); int video_stream = -1; AVRational time_base{1, 1000}; + AVBSFContext* bsf_ctx = nullptr; AVDictionary* opts = nullptr; if (ffmpeg_force_tcp_) av_dict_set(&opts, "rtsp_transport", "tcp", 0); if (avformat_open_input(&fmt_ctx, url_.c_str(), nullptr, &opts) < 0) { std::cerr << "[input_rtsp] avformat_open_input failed: " << url_ << "\n"; av_dict_free(&opts); + if (bsf_ctx) av_bsf_free(&bsf_ctx); + if (filt_pkt) av_packet_free(&filt_pkt); Cleanup(fmt_ctx, nullptr, pkt, nullptr); if (fallback_to_stub_on_fail_) { LoopStub(); @@ -450,6 +462,8 @@ private: av_dict_free(&opts); if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) { std::cerr << "[input_rtsp] avformat_find_stream_info failed\n"; + if (bsf_ctx) av_bsf_free(&bsf_ctx); + if (filt_pkt) av_packet_free(&filt_pkt); Cleanup(fmt_ctx, nullptr, pkt, nullptr); std::this_thread::sleep_for(seconds(backoff)); backoff = std::min(backoff_max, backoff * 2); @@ -464,6 +478,8 @@ private: } if (video_stream < 0) { std::cerr << "[input_rtsp] no video stream\n"; + if (bsf_ctx) av_bsf_free(&bsf_ctx); + if (filt_pkt) av_packet_free(&filt_pkt); Cleanup(fmt_ctx, nullptr, pkt, nullptr); std::this_thread::sleep_for(seconds(backoff)); backoff = std::min(backoff_max, backoff * 2); @@ -476,6 +492,8 @@ private: else if (codec_id == AV_CODEC_ID_HEVC) coding = MPP_VIDEO_CodingHEVC; else { std::cerr << "[input_rtsp] unsupported codec for mpp\n"; + if (bsf_ctx) av_bsf_free(&bsf_ctx); + if (filt_pkt) av_packet_free(&filt_pkt); Cleanup(fmt_ctx, nullptr, pkt, nullptr); std::this_thread::sleep_for(seconds(backoff)); backoff = std::min(backoff_max, backoff * 2); @@ -485,12 +503,38 @@ private: MppDecoderWrapper dec; if (!dec.Init(coding)) { std::cerr << "[input_rtsp] mpp init failed\n"; + if (bsf_ctx) av_bsf_free(&bsf_ctx); + if (filt_pkt) av_packet_free(&filt_pkt); Cleanup(fmt_ctx, nullptr, pkt, nullptr); std::this_thread::sleep_for(seconds(backoff)); backoff = std::min(backoff_max, backoff * 2); continue; } + auto ensure_bsf = [&]() -> bool { + if (bsf_ctx) return true; + const char* bsf_name = nullptr; + if (codec_id == AV_CODEC_ID_H264) bsf_name = "h264_mp4toannexb"; + else if (codec_id == AV_CODEC_ID_HEVC) bsf_name = "hevc_mp4toannexb"; + if (!bsf_name) return false; + const AVBitStreamFilter* bsf = av_bsf_get_by_name(bsf_name); + if (!bsf) return false; + if (av_bsf_alloc(bsf, &bsf_ctx) < 0) { + bsf_ctx = nullptr; + return false; + } + if (avcodec_parameters_copy(bsf_ctx->par_in, fmt_ctx->streams[video_stream]->codecpar) < 0) { + av_bsf_free(&bsf_ctx); + return false; + } + bsf_ctx->time_base_in = fmt_ctx->streams[video_stream]->time_base; + if (av_bsf_init(bsf_ctx) < 0) { + av_bsf_free(&bsf_ctx); + return false; + } + return true; + }; + backoff = std::max(1, reconnect_sec_); int read_fail = 0; while (running_.load()) { @@ -506,11 +550,27 @@ private: } int64_t pts_us = pkt->pts == AV_NOPTS_VALUE ? 0 : av_rescale_q(pkt->pts, time_base, {1, 1000000}); - dec.Decode(pkt->data, pkt->size, false, pts_us, - [&](MppFrame frm) { PushFrameFromMpp(frm); }); + + if (IsAnnexB(pkt->data, static_cast(pkt->size))) { + dec.Decode(pkt->data, static_cast(pkt->size), false, pts_us, + [&](MppFrame frm) { PushFrameFromMpp(frm); }); + } else if (ensure_bsf()) { + if (av_bsf_send_packet(bsf_ctx, pkt) == 0) { + while (av_bsf_receive_packet(bsf_ctx, filt_pkt) == 0) { + dec.Decode(filt_pkt->data, static_cast(filt_pkt->size), false, pts_us, + [&](MppFrame frm) { PushFrameFromMpp(frm); }); + av_packet_unref(filt_pkt); + } + } + } else { + std::cerr << "[input_rtsp] non-AnnexB bitstream but bsf init failed; mpp decode may produce no frames\n"; + } + av_packet_unref(pkt); } + if (bsf_ctx) av_bsf_free(&bsf_ctx); + if (filt_pkt) av_packet_free(&filt_pkt); Cleanup(fmt_ctx, nullptr, pkt, nullptr); if (!running_.load()) break; std::this_thread::sleep_for(seconds(std::max(1, reconnect_sec_))); @@ -580,7 +640,7 @@ private: PushToDownstream(frame); - if (frame_id_ % 100 == 0) { + if (frame_id_ <= 3 || frame_id_ % 100 == 0) { std::cout << "[input_rtsp] mpp frame " << frame->frame_id << " queue=" << (out_queues_.empty() ? 0 : out_queues_[0]->Size()) << " drops=" << (out_queues_.empty() ? 0 : out_queues_[0]->DroppedCount())