修bug
This commit is contained in:
parent
644fb590fa
commit
aad9b3bf68
@ -20,6 +20,7 @@ extern "C" {
|
||||
|
||||
#ifdef RK3588_ENABLE_FFMPEG
|
||||
extern "C" {
|
||||
#include <libavcodec/bsf.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
@ -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<size_t>(pkt->size))) {
|
||||
dec.Decode(pkt->data, static_cast<size_t>(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<size_t>(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())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user