为什么 AVFrame pts 值不影响帧的比特率?

如何解决为什么 AVFrame pts 值不影响帧的比特率?

我正在尝试代码实时屏幕共享,我注意到 H264 编解码器不会对每一帧进行恒定时间编码。这导致无法使用 context->time_base 编码完全相同数量的帧速率。当我们每秒编码的帧数少于 time_base 时,秒的比特率会低于我们设置的值。

修改了 libav 的示例编码代码并放置了 1/1000 时基并仅提供 10 帧。我增加了与 time_base 相关的 frame->pts,但比特率仍然保持在较低水平。

对于结果,我只是将 context->time_base 更改为 {1,1000},{1,10} 等

1/1000 时基(每秒总和 1989 字节):

encoded frame 0 (size=1169)
encoded frame 100 (size=95)
encoded frame 200 (size=92)
encoded frame 300 (size=102)
encoded frame 400 (size=90)
encoded frame 500 (size=90)
encoded frame 600 (size=90)
encoded frame 700 (size=83)
encoded frame 800 (size=95)
encoded frame 900 (size=83)

1/10 时基(每秒总和 95324 字节):

encoded frame 0 (size=14187)
encoded frame 1 (size=6053)
encoded frame 2 (size=8530)
encoded frame 3 (size=9277)
encoded frame 4 (size=9508)
encoded frame 5 (size=11163)
encoded frame 6 (size=9685)
encoded frame 7 (size=9346)
encoded frame 8 (size=7662)
encoded frame 9 (size=9913)

代码

#include <assert.h>
#include <stdio.h>
#include <libavcodec/avcodec.h>

static void encode(AVCodecContext *context,AVFrame *frame,AVPacket *pkt,FILE *outfile){
    int ret = avcodec_send_frame(context,frame);
    assert(ret >= 0);
    while(ret >= 0){
        ret = avcodec_receive_packet(context,pkt);
        if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if(ret < 0)
            assert(0);
        printf("encoded frame %lld (size=%d)\n",pkt->pts,pkt->size);
        fwrite(pkt->data,1,pkt->size,outfile);
        av_packet_unref(pkt);
    }
}

int main(int argc,char **argv){
    if(argc <= 1){
        fprintf(stderr,"Usage: %s <output file>\n",argv[0]);
        exit(0);
    }
    av_log_set_level(AV_LOG_QUIET);
    const char *filename = argv[1];
    const AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);
    assert(codec);
    AVCodecContext *context = avcodec_alloc_context3(codec);
    assert(context);
    AVFrame *frame = av_frame_alloc();
    assert(frame);
    AVPacket *pkt = av_packet_alloc();
    assert(pkt);
    context->bit_rate = 800000;
    context->width = 1280;
    context->height = 720;
    context->time_base = (AVRational){1,1000};
    context->pix_fmt = AV_PIX_FMT_YUV420P;
    AVDictionary *dict = 0;
    assert(av_dict_set(&dict,"preset","veryfast",0) >= 0);
    assert(av_dict_set(&dict,"tune","zerolatency",0) >= 0);
    assert(avcodec_open2(context,codec,&dict) >= 0);
    FILE *f = fopen(filename,"wb");
    assert(f);
    frame->format = context->pix_fmt;
    frame->width  = context->width;
    frame->height = context->height;
    assert(av_frame_get_buffer(frame,0) >= 0);
    for(int i = 0; i < 10; i++){
        for(int y = 0; y < context->height; y++){
            for(int x = 0; x < context->width; x++){
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }
        for(int y = 0; y < context->height / 2; y++){
            for(int x = 0; x < context->width / 2; x++){
                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
            }
        }
        frame->pts = i * (context->time_base.den / 10);
        encode(context,frame,pkt,f);
    }
    fclose(f);
    avcodec_free_context(&context);
    av_frame_free(&frame);
    av_packet_free(&pkt);
    return 0;
}

我们如何在不同的时基和帧速率下保持正确的比特率?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?