ffmpeg源码简析(八)解码 av_read_frame(),avcodec_decode_video2(),avformat_close_input()

1.av_read_frame()

av_read_frame()的作用是读取码流中的音频若干帧或者视频一帧。例如,解码视频的时候,每解码一个视频帧,需要先调用 av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码(例如H.264中一帧压缩数据通常对应一个NAL)。

通过av_read_packet(***),读取一个包,需要说明的是此函数必须是包含整数帧的,不存在半帧的情况,以ts流为例,是读取一个完整的PES包(一个完整pes包包含若干视频或音频es包),读取完毕后,通过av_parser_parse2(***)分析出视频一帧(或音频若干帧),返回,下次进入循环的时候,如果上次的数据没有完全取完,则st = s->cur_st;不会是NULL,即再此进入av_parser_parse2(***)流程,而不是下面的av_read_packet(**)流程,这样就保证了,如果读取一次包含了N帧视频数据(以视频为例),则调用av_read_frame(***)N次都不会去读数据,而是返回第一次读取的数据,直到全部解析完毕。

av_read_frame()的声明位于libavformat\avformat.h,如下所示。

int av_read_frame(AVFormatContext *s, AVPacket *pkt); 

av_read_frame()使用方法在注释中写得很详细,用中文简单描述一下它的两个参数:

s:输入的AVFormatContext

pkt:输出的AVPacket

如果返回0则说明读取正常。

av_read_frame()的定义位于libavformat\utils.c,如下所示:

    //获取一个AVPacket  
    /* 
     * av_read_frame - 新版本的ffmpeg用的是av_read_frame,而老版本的是av_read_packet 
     * 。区别是av_read_packet读出的是包,它可能是半帧或多帧,不保证帧的完整性。av_read_frame对 
     * av_read_packet进行了封装,使读出的数据总是完整的帧 
     */  
    int av_read_frame(AVFormatContext *s, AVPacket *pkt)  
    {  
        const int genpts = s->flags & AVFMT_FLAG_GENPTS;  
        int          eof = 0;  

        if (!genpts)  
            /** 
             * This buffer is only needed when packets were already buffered but 
             * not decoded, for example to get the codec parameters in MPEG 
             * streams. 
             * 一般情况下会调用read_frame_internal(s, pkt) 
             * 直接返回 
             */  
            return s->packet_buffer ? read_from_packet_buffer(s, pkt) :  
                                      read_frame_internal(s, pkt);  

        for (;;) {  
            int ret;  
            AVPacketList *pktl = s->packet_buffer;  

            if (pktl) {  
                AVPacket *next_pkt = &pktl->pkt;  

                if (next_pkt->dts != AV_NOPTS_VALUE) {  
                    int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits;  
                    while (pktl && next_pkt->pts == AV_NOPTS_VALUE) {  
                        if (pktl->pkt.stream_index == next_pkt->stream_index &&  
                            (av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2LL << (wrap_bits - 1)) < 0) &&  
                             av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) { //not b frame  
                            next_pkt->pts = pktl->pkt.dts;  
                        }  
                        p
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值