如何解决为什么 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 举报,一经查实,本站将立刻删除。