1 解码流程
av_read_frame 将解封装后的数据存入
AVPacket
,avcodec_send_packet()函数将原始AVPacket
送入解码器,
avcodec_receive_frame() 函数将解码后的数据存入AVFrame。
这个解码过程
必定会涉及到内存分配回收问题。在 FFMpeg 中,内存 IO 叫做 buffered IO
,是指将一块内存缓冲区用作 FFmpeg 的输入或者输出,与内存 IO 操作对应的是指定 URL
作为 FFmpeg 的输入或输出。
AVPacket 音视频压缩数据
AVFrame解码后的原始图像数据
2 内存模型
两个avpacket指向同一AVBuffer空间,FFmpeg使用的引用计数的机制来管理。
AVBuffer
是FFmpeg
中的缓冲区,一开始时AVBuffer
的引用计数(refcount
)初始化为 0
当有新的Packet
引用共享的缓存空间时,就将引用计数再 +1
当Packet
释放掉对AVBuffer
这块共享缓存空间的引用时,将引用计数 -1
只有当refcount
为 0 的时候,才会释放掉缓存空间AVBuffer
AVBuffer
表示数据缓冲区本身,只能通过AVBufferRef
访问。
AVBufferRef
表示单个对AVBuffer
的引用,它是一个可以由调用者直接调用的对象。
附录:
AVPacket API
|
AVFrame API
|
FFMPEG API /* Initialize libavformat and register all the muxers, demuxers and protocols */ //Do global initialization of network components int avformat_network_init(void); /*Allocate and initialize an AVIOContext for buffered I/O. 读写buffer 3 param:write_flag Set to 1 if the buffer should be writable, 0 otherwise 5 param:read_packet A function for refilling the buffer, may be NULL 6 param:write_packet A function for writing the buffer contents, may be NULL 7param:seek A function for seeking to specified byte position, may be NULL return:Allocated AVIOContext or NULL on failure*/ AVIOContext* pIOCtx = avio_alloc_context(m_pAvioBuffer, buffer_size, 0, this, &FFmpegPlayCore::EtvxReadFunc, 0, &FFmpegPlayCore::EtvxSeekFunc); //Allocate an AVFormatContext. /* Open an input stream and read the header. The codecs are not opened */ int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options); /* Read packets of a media file to get stream information */ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); /* Seek to timestamp ts */ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); /* 获取音视频对应的stream_index */ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, //解封装后的数据存入每个AVPacket int av_read_frame(AVFormatContext *s, AVPacket *pkt); //Find a registered decoder with a matching codec ID AVCodec *avcodec_find_decoder(enum AVCodecID id); //Find a registered decoder with the specified name AVCodec *avcodec_find_decoder_by_name(const char *name); //打开解码器 int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); //Supply raw packet data as input to a decoder int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); //Read encoded data from the encoder int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); //解码 int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, //Return decoded output data from a decoder int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); //Supply a raw video or audio frame to the encoder int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); /* Start playing a network-based stream (e.g. RTSP stream) at the current position. */ /* Pause a network-based stream (e.g. RTSP stream) ,Use av_read_play() to resume it */
|