修bug
Some checks are pending
CI / host-build (push) Waiting to run
CI / rk3588-cross-build (push) Waiting to run

This commit is contained in:
sladro 2026-01-05 17:01:22 +08:00
parent cd2b8817d3
commit d3a376f548

View File

@ -320,6 +320,13 @@ private:
return false;
}
static int GetAnnexBStartCodeSize(const uint8_t* data, size_t size) {
if (!data || size < 4) return 0;
if (data[0] == 0 && data[1] == 0 && data[2] == 1) return 3;
if (data[0] == 0 && data[1] == 0 && data[2] == 0 && data[3] == 1) return 4;
return 0;
}
struct MppDecoderWrapper {
~MppDecoderWrapper() { Shutdown(); }
@ -329,23 +336,6 @@ private:
ret = mpp_init(ctx, MPP_CTX_DEC, type);
if (ret != MPP_OK) return false;
// Packet buffer group (bitstream input). MPP will pick the best allocator available.
if (!pkt_group) {
auto try_group = [&](MppBufferType t) -> bool {
return mpp_buffer_group_get(&pkt_group, t, MPP_BUFFER_INTERNAL, MODULE_TAG, __FUNCTION__) == MPP_OK;
};
// NOTE: Packet(bitstream) buffer should be CPU-accessible; use NORMAL first to avoid mmap/ptr issues.
if (!try_group(MPP_BUFFER_TYPE_NORMAL) &&
!try_group(MPP_BUFFER_TYPE_ION) &&
!try_group(MPP_BUFFER_TYPE_DRM) &&
!try_group(MPP_BUFFER_TYPE_DMA_HEAP)) {
pkt_group = nullptr;
return false;
}
mpp_buffer_group_limit_config(pkt_group, 0, 8);
}
MppDecCfg cfg = nullptr;
mpp_dec_cfg_init(&cfg);
ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);
@ -358,10 +348,6 @@ private:
}
void Shutdown() {
if (pkt_group) {
mpp_buffer_group_put(pkt_group);
pkt_group = nullptr;
}
if (frame_group) {
mpp_buffer_group_put(frame_group);
frame_group = nullptr;
@ -377,29 +363,27 @@ private:
const std::function<void(MppFrame)>& on_frame) {
if (!ctx || !mpi || !data || size == 0) return false;
if (!pkt_group) return false;
MppBuffer pkt_buf = nullptr;
if (mpp_buffer_get(pkt_group, &pkt_buf, size) != MPP_OK || !pkt_buf) {
// Use mpp_packet_copy_init so packet memory lifetime is independent of AVPacket.
MppPacket src = nullptr;
MPP_RET ret = mpp_packet_init(&src, const_cast<uint8_t*>(data), size);
if (ret != MPP_OK || !src) {
if (++fail_copy_init_ <= 3 || fail_copy_init_ % 200 == 0) {
std::cerr << "[input_rtsp] mpp_packet_init failed ret=" << ret << " size=" << size << "\n";
}
return false;
}
void* dst = mpp_buffer_get_ptr(pkt_buf);
if (!dst) {
mpp_buffer_put(pkt_buf);
return false;
}
std::memcpy(dst, data, size);
MppPacket packet = nullptr;
if (mpp_packet_init_with_buffer(&packet, pkt_buf) != MPP_OK || !packet) {
mpp_buffer_put(pkt_buf);
ret = mpp_packet_copy_init(&packet, src);
mpp_packet_deinit(&src);
if (ret != MPP_OK || !packet) {
if (++fail_copy_init_ <= 3 || fail_copy_init_ % 200 == 0) {
std::cerr << "[input_rtsp] mpp_packet_copy_init failed ret=" << ret << " size=" << size << "\n";
}
return false;
}
mpp_buffer_put(pkt_buf); // packet holds reference
mpp_packet_set_data(packet, dst);
mpp_packet_set_size(packet, size);
mpp_packet_set_pos(packet, dst);
mpp_packet_set_pos(packet, mpp_packet_get_data(packet));
mpp_packet_set_length(packet, size);
mpp_packet_set_pts(packet, pts_us);
mpp_packet_clr_eos(packet);
@ -409,11 +393,20 @@ private:
int put_tries = 0;
while (true) {
if (!pkt_done) {
if (mpi->decode_put_packet(ctx, packet) == MPP_OK) {
MPP_RET put_ret = mpi->decode_put_packet(ctx, packet);
if (put_ret == MPP_OK) {
pkt_done = true;
} else {
if (++fail_put_packet_ret_ <= 3 || fail_put_packet_ret_ % 200 == 0) {
std::cerr << "[input_rtsp] decode_put_packet ret=" << put_ret
<< " tries=" << put_tries << "\n";
}
usleep(2000);
if (++put_tries >= 500) {
if (++fail_put_packet_ <= 3 || fail_put_packet_ % 200 == 0) {
std::cerr << "[input_rtsp] decode_put_packet timeout ret=" << put_ret
<< " tries=" << put_tries << "\n";
}
mpp_packet_deinit(&packet);
return false;
}
@ -426,7 +419,12 @@ private:
usleep(2000);
continue;
}
if (ret != MPP_OK) break;
if (ret != MPP_OK) {
if (++fail_get_frame_ <= 3 || fail_get_frame_ % 200 == 0) {
std::cerr << "[input_rtsp] decode_get_frame ret=" << ret << "\n";
}
break;
}
if (frame) {
if (mpp_frame_get_info_change(frame)) {
@ -447,6 +445,41 @@ private:
return pkt_done;
}
bool SendExtraData(const uint8_t* data, size_t size) {
if (!ctx || !mpi || !data || size == 0) return false;
if (!IsAnnexB(data, size)) {
std::cerr << "[input_rtsp] extra_data is not AnnexB; mpp may ignore it\n";
}
MppPacket src = nullptr;
MPP_RET ret = mpp_packet_init(&src, const_cast<uint8_t*>(data), size);
if (ret != MPP_OK || !src) return false;
MppPacket pkt = nullptr;
ret = mpp_packet_copy_init(&pkt, src);
mpp_packet_deinit(&src);
if (ret != MPP_OK || !pkt) return false;
mpp_packet_set_pos(pkt, mpp_packet_get_data(pkt));
mpp_packet_set_length(pkt, size);
mpp_packet_set_pts(pkt, 0);
mpp_packet_set_extra_data(pkt);
int tries = 0;
while (tries++ < 200) {
MPP_RET put_ret = mpi->decode_put_packet(ctx, pkt);
if (put_ret == MPP_OK) {
mpp_packet_deinit(&pkt);
return true;
}
usleep(2000);
}
std::cerr << "[input_rtsp] extra_data decode_put_packet timeout\n";
mpp_packet_deinit(&pkt);
return false;
}
void HandleInfoChange() {
if (!ctx || !mpi || !frame) return;
MppBufferGroup group = frame_group;
@ -475,9 +508,12 @@ private:
MppCtx ctx = nullptr;
MppApi* mpi = nullptr;
MppBufferGroup pkt_group = nullptr;
MppBufferGroup frame_group = nullptr;
MppFrame frame = nullptr;
uint64_t fail_copy_init_ = 0;
uint64_t fail_put_packet_ = 0;
uint64_t fail_put_packet_ret_ = 0;
uint64_t fail_get_frame_ = 0;
};
void LoopFfmpegMpp() {
@ -587,6 +623,29 @@ private:
return true;
};
// Send codec extra data (SPS/PPS or VPS/SPS/PPS). Many RTSP streams rely on SDP extradata.
// Prefer bsf-converted extradata when available.
bool bsf_ok = ensure_bsf();
const AVCodecParameters* par = fmt_ctx->streams[video_stream]->codecpar;
if (par && par->extradata && par->extradata_size > 0) {
const uint8_t* extra = par->extradata;
size_t extra_size = static_cast<size_t>(par->extradata_size);
if (bsf_ok && bsf_ctx && bsf_ctx->par_out && bsf_ctx->par_out->extradata && bsf_ctx->par_out->extradata_size > 0) {
extra = bsf_ctx->par_out->extradata;
extra_size = static_cast<size_t>(bsf_ctx->par_out->extradata_size);
}
if (extra && extra_size > 0) {
std::cout << "[input_rtsp] send extra_data size=" << extra_size
<< " annexb=" << (IsAnnexB(extra, extra_size) ? 1 : 0)
<< "\n";
if (!dec.SendExtraData(extra, extra_size)) {
std::cerr << "[input_rtsp] send extra_data failed\n";
}
}
}
backoff = std::max(1, reconnect_sec_);
int read_fail = 0;
uint64_t pkt_count = 0;
@ -617,6 +676,19 @@ private:
: av_rescale_q(pkt->pts, time_base, {1, 1000000});
if (IsAnnexB(pkt->data, static_cast<size_t>(pkt->size))) {
if (pkt_count <= 10) {
int sc = GetAnnexBStartCodeSize(pkt->data, static_cast<size_t>(pkt->size));
if (sc > 0 && static_cast<size_t>(sc) < static_cast<size_t>(pkt->size)) {
uint8_t b0 = pkt->data[sc];
int h264_type = b0 & 0x1F;
int h265_type = (b0 >> 1) & 0x3F;
std::cout << "[input_rtsp] pkt#" << pkt_count
<< " nal(h264)=" << h264_type
<< " nal(h265)=" << h265_type
<< " first_byte=0x" << std::hex << static_cast<int>(b0) << std::dec
<< "\n";
}
}
if (!dec.Decode(pkt->data, static_cast<size_t>(pkt->size), false, pts_us,
[&](MppFrame frm) { PushFrameFromMpp(frm); })) {
if (++decode_fail <= 3 || decode_fail % 200 == 0) {