修bug
This commit is contained in:
parent
cd2b8817d3
commit
d3a376f548
@ -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) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user