openal中使用现代C++智能指针管理ffmpeg中裸指针的用法

裸指针包装


/* Define unique_ptrs to auto-cleanup associated ffmpeg objects. */
struct AVIOContextDeleter {
    void operator()(AVIOContext *ptr) { avio_closep(&ptr); }
};
using AVIOContextPtr = std::unique_ptr<AVIOContext,AVIOContextDeleter>;

struct AVFormatCtxDeleter {
    void operator()(AVFormatContext *ptr) { avformat_close_input(&ptr); }
};
using AVFormatCtxPtr = std::unique_ptr<AVFormatContext,AVFormatCtxDeleter>;

struct AVCodecCtxDeleter {
    void operator()(AVCodecContext *ptr) { avcodec_free_context(&ptr); }
};
using AVCodecCtxPtr = std::unique_ptr<AVCodecContext,AVCodecCtxDeleter>;

struct AVPacketDeleter {
    void operator()(AVPacket *pkt) { av_packet_free(&pkt); }
};
using AVPacketPtr = std::unique_ptr<AVPacket,AVPacketDeleter>;

struct AVFrameDeleter {
    void operator()(AVFrame *ptr) { av_frame_free(&ptr); }
};
using AVFramePtr = std::unique_ptr<AVFrame,AVFrameDeleter>;

struct SwrContextDeleter {
    void operator()(SwrContext *ptr) { swr_free(&ptr); }
};
using SwrContextPtr = std::unique_ptr<SwrContext,SwrContextDeleter>;

struct SwsContextDeleter {
    void operator()(SwsContext *ptr) { sws_freeContext(ptr); }
};
using SwsContextPtr = std::unique_ptr<SwsContext,SwsContextDeleter>;

对象


struct ChannelLayout : public AVChannelLayout {
    ChannelLayout() : AVChannelLayout{} { }
    ~ChannelLayout() { av_channel_layout_uninit(this); }
};

智能指针使用和轮子—解包队列

template<size_t SizeLimit>
class DataQueue {
    std::mutex mPacketMutex, mFrameMutex;
    std::condition_variable mPacketCond;
    std::condition_variable mInFrameCond, mOutFrameCond;

    std::deque<AVPacketPtr> mPackets;
    size_t mTotalSize{0};
    bool mFinished{false};

    AVPacketPtr getPacket()
    {
        std::unique_lock<std::mutex> plock{mPacketMutex};
        while(mPackets.empty() && !mFinished)
            mPacketCond.wait(plock);
        if(mPackets.empty())
            return nullptr;

        auto ret = std::move(mPackets.front());
        mPackets.pop_front();
        mTotalSize -= static_cast<unsigned int>(ret->size);
        return ret;
    }

public:
    int sendPacket(AVCodecContext *codecctx)
    {
        AVPacketPtr packet{getPacket()};

        int ret{};
        {
            std::unique_lock<std::mutex> flock{mFrameMutex};
            while((ret=avcodec_send_packet(codecctx, packet.get())) == AVERROR(EAGAIN))
                mInFrameCond.wait_for(flock, milliseconds{50});
        }
        mOutFrameCond.notify_one();

        if(!packet)
        {
            if(!ret) return AVErrorEOF;
            std::cerr<< "Failed to send flush packet: "<<ret <<std::endl;
            return ret;
        }
        if(ret < 0)
            std::cerr<< "Failed to send packet: "<<ret <<std::endl;
        return ret;
    }

    int receiveFrame(AVCodecContext *codecctx, AVFrame *frame)
    {
        int ret{};
        {
            std::unique_lock<std::mutex> flock{mFrameMutex};
            while((ret=avcodec_receive_frame(codecctx, frame)) == AVERROR(EAGAIN))
                mOutFrameCond.wait_for(flock, milliseconds{50});
        }
        mInFrameCond.notify_one();
        return ret;
    }

    void setFinished()
    {
        {
            std::lock_guard<std::mutex> _{mPacketMutex};
            mFinished = true;
        }
        mPacketCond.notify_one();
    }

    void flush()
    {
        {
            std::lock_guard<std::mutex> _{mPacketMutex};
            mFinished = true;

            mPackets.clear();
            mTotalSize = 0;
        }
        mPacketCond.notify_one();
    }

    bool put(const AVPacket *pkt)
    {
        {
            std::unique_lock<std::mutex> lock{mPacketMutex};
            if(mTotalSize >= SizeLimit || mFinished)
                return false;

            mPackets.push_back(AVPacketPtr{av_packet_alloc()});
            if(av_packet_ref(mPackets.back().get(), pkt) != 0)
            {
                mPackets.pop_back();
                return true;
            }

            mTotalSize += static_cast<unsigned int>(mPackets.back()->size);
        }
        mPacketCond.notify_one();
        return true;
    }
};

你可能感兴趣的:(C++,c++,ffmpeg,开发语言)