ffmpeg /x264视频流编解码末尾丢帧问题分析和解决

8 篇文章 1 订阅
7 篇文章 0 订阅

一:问题

int avcodec_encode_video2 ( AVCodecContext *  avctx,


AVPacket *  avpkt,


const AVFrame *  frame,


int *  got_packet_ptr 

)


Encode a frame of video.
Takes input raw video data from frame and writes the next output packet, if available, to avpkt. The output packet does not necessarily contain data for the most recent frame, as encoders can delay and reorder input frames internally as needed.

int avcodec_decode_video2 ( AVCodecContext *  avctx,


AVFrame *  picture,


int *  got_picture_ptr,


const AVPacket *  avpkt 

)


Decode the video frame of size avpkt->size from avpkt->data into picture.

Some decoders may support multiple frames in a single AVPacket, such decoders would then just decode the first frame.



官网api的提到:

Takes input raw video data from frame and writes the next output packet, if available, to avpkt. The output packet does not necessarily contain data for the most recent frame, as encoders can delay and reorder input frames internally as needed.


二原因:

拿编码来说,丢帧原因如图:




这被称为编码延迟。延迟原因又分为两种,一是计算延迟,而是缓存延迟。

所以:

h->frames.i_delay =
                                 param->i_sync_lookahead +                        // 前向考虑帧数
                                max ( param->i_bframe,                               // B帧数量
                                          param->rc.i_lookahead)  +                 // 码率控制前向考虑帧数

通过设置参数将编码和获取的帧间隔缩小到0,使用“zerolatency"的tune设定编码模型,详细:

三 解决

编码延迟就需要在编码所有yuv数据之后必须flush。

int vflush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index) {
    int ret = 0;
    int got_frame;
    AVPacket enc_pkt;
    if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities
            & CODEC_CAP_DELAY))
        return 0;
    av_init_packet(&enc_pkt);
    while (IS_GOING) {
        enc_pkt.data = NULL;
        enc_pkt.size = 0;
        ret = avcodec_encode_video2(fmt_ctx->streams[stream_index]->codec,
                &enc_pkt, NULL, &got_frame);

        if (ret < 0)
            break;
        if (!got_frame) {
            ret = 0;
            break;
        }
        ret = av_write_frame(fmt_ctx, &enc_pkt);
        printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",
                enc_pkt.size);
        av_free_packet(&enc_pkt);

        if (ret < 0)
            break;
    }

    return ret;
}



解码同理,在 av_read_frame到没有avpacket可以读取之后,要继续 调用 avcodec_encode_video2,将视频末尾帧解码出来。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值