微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用ASIO为ffmpeg实现interrupt_callback

如何解决使用ASIO为ffmpeg实现interrupt_callback

我正在尝试使用 ASIO 计时器为 interrupt_callbackavformat_open_input 以及可能用于其他功能正确实现 av_read_frame。接收 udp 视频流时我无法让它工作。

我编写了一个使用 ASIO 计时器等待一段时间的类。它的构造函数io_context 执行的线程中获取一个 avformat_open_input 以及要等待的整个超时时间。认情况下,它每次等待 20 毫秒,但可以设置等待更长的时间。

class InterruptCallback
{
public:

    constexpr static std::chrono::milliseconds basic_period()
    {
        return std::chrono::milliseconds(20);
    }

    explicit InterruptCallback(asio::io_context &asioContext,std::chrono::milliseconds timeout,std::chrono::milliseconds period =
                               basic_period())
            : waitingPeriod_(period),attempts_(timeout / waitingPeriod_),timer_(asioContext)
    {
        attempts_ = attempts_ ? attempts_ : 1;
    }

    int wait()
    {
        timer_.expires_after(waitingPeriod_);
        timer_.wait();
        return int(!--attempts_);
    }

    static int wait(void *opaqueCallback)
    {
        auto callback = reinterpret_cast<InterruptCallback *>(opaqueCallback);
        return callback->wait();
    }

private:
    std::chrono::milliseconds waitingPeriod_;
    size_t attempts_;

    asio::steady_timer timer_;
};

当没有接收到 udp 流时,此方法有效。当接收到 udp 时,它的返回速度也相对较快。

但是,当我设置 AVFormatContext::interrupt_callback 时,我在解码时遇到很多错误avformat_find_stream_info 可以足够快地返回,但 AVCodecContext 将无效。 或者可能需要很长时间才能执行。

    asio::io_context mainthreadcontext{};

    AVFormatContext *pformatContext = avformat_alloc_context();

    {
        InterruptCallback interruptCallback{mainthreadcontext,std::chrono::milliseconds(2000)
        };

        pformatContext->interrupt_callback.callback = &InterruptCallback::wait;
        pformatContext->interrupt_callback.opaque = &interruptCallback;

        const auto resOpen = avformat_open_input(&pformatContext,containerAddress.c_str(),nullptr,nullptr);
        if (resOpen < 0)
        {
            std::cerr << "Failed to open stream from: " << containerAddress << std::endl;
            return -1;
        }
    }
    auto avFormatExit = sg::make_scope_exit(
            [&pformatContext]
            {
                avformat_close_input(&pformatContext);
            });

    pformatContext->flags = AVFMT_FLAG_NOBUFFER | AVFMT_FLAG_FLUSH_PACKETS;

    int error = avformat_find_stream_info(pformatContext,nullptr);

它可能发生在我查询流信息的行上,但也经常用于解码循环。 以下是一些可能的错误

[h264 @ 00000000027f4000] non-existing PPS 0 referenced
[h264 @ 00000000027f4000] non-existing PPS 0 referenced
[h264 @ 00000000027f4000] decode_slice_header error
[h264 @ 00000000027f4000] no frame!
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000027f4000] concealing 7217 DC,7217 AC,7217 MV errors in I frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000027f4000] concealing 7588 DC,7588 AC,7588 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000027f4000] error while decoding MB 83 5,bytestream -6
[h264 @ 00000000027f4000] concealing 7526 DC,7526 AC,7526 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000027f4000] concealing 7072 DC,7072 AC,7072 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000027f4000] concealing 7651 DC,7651 AC,7651 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000027f4000] concealing 5806 DC,5806 AC,5806 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000027f4000] left block unavailable for requested intra mode
[h264 @ 00000000027f4000] error while decoding MB 0 5,bytestream 8107
[h264 @ 00000000027f4000] concealing 7609 DC,7609 AC,7609 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6669 DC,6669 AC,6669 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7254 DC,7254 AC,7254 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7048 DC,7048 AC,7048 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7061 DC,7061 AC,7061 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7220 DC,7220 AC,7220 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 5722 DC,5722 AC,5722 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7230 DC,7230 AC,7230 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7085 DC,7085 AC,7085 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7745 DC,7745 AC,7745 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6907 DC,6907 AC,6907 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7301 DC,7301 AC,7301 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 5664 DC,5664 AC,5664 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] error while decoding MB 105 8,bytestream -8
[h264 @ 00000000051a0040] concealing 7144 DC,7144 AC,7144 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7487 DC,7487 AC,7487 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6912 DC,6912 AC,6912 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] error while decoding MB 39 8,bytestream -6
[h264 @ 00000000051a0040] concealing 7210 DC,7210 AC,7210 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 5262 DC,5262 AC,5262 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] error while decoding MB 54 8,bytestream -5
[h264 @ 00000000051a0040] concealing 7195 DC,7195 AC,7195 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7298 DC,7298 AC,7298 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6819 DC,6819 AC,6819 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 5692 DC,5692 AC,5692 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6684 DC,6684 AC,6684 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7600 DC,7600 AC,7600 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6123 DC,6123 AC,6123 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7689 DC,7689 AC,7689 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6846 DC,6846 AC,6846 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] left block unavailable for requested intra4x4 mode -1
[h264 @ 00000000051a0040] error while decoding MB 0 10,bytestream 1892
[h264 @ 00000000051a0040] concealing 7009 DC,7009 AC,7009 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 5288 DC,5288 AC,5288 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7932 DC,7932 AC,7932 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 7039 DC,7039 AC,7039 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] error while decoding MB 105 11,bytestream -5
[h264 @ 00000000051a0040] concealing 6784 DC,6784 AC,6784 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6918 DC,6918 AC,6918 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] concealing 6483 DC,6483 AC,6483 MV errors in P frame
[h264 @ 00000000051a0040] error while decoding MB 118 1,bytestream -10
[h264 @ 00000000051a0040] concealing 7971 DC,7971 AC,7971 MV errors in P frame
[mpegts @ 00000000027dea40] PES packet size mismatch
[h264 @ 00000000051a0040] QP 4294967266 out of range
[h264 @ 00000000051a0040] decode_slice_header error
[h264 @ 00000000051a0040] no frame!
Error sending packet for decoding

Process finished with exit code 1

当我设置 interrupt_callback 时,不会发生错误,可以很快找到流信息。

所以,问题是:

  1. 在实现中断回调时我做错了什么?
  2. 当我从 avformat_find_stream_info 收到无效的编解码器上下文时,为什么我没有收到错误消息?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。