裸指针包装
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 ; }
} ;