请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

h264编码之后,视频数据最后几秒丢失了

while (av_read_frame(fmt_ctx, &pkt) >= 0 && count_++ < 100)
{
    // fwrite(pkt.data, 1, pkt.size, outfile_yuv);
    // fflush(outfile_yuv);
    memcpy(frame->data[0], pkt.data, 1280 * 720 * 2);
    fwrite(pkt.data, 1, pkt.size, outfile_yuv);
    fflush(outfile_yuv);
    sws_scale_frame(sws_ctx, outFrame, frame);
    outFrame->pts = count_;
    encode(codex_ctx, outFrame, outpkt, outfile_h264);
    av_packet_unref(&pkt);
}
encode(codex_ctx, NULL, outpkt, outfile_h264);
avformat_close_input(&fmt_ctx);
fclose(outfile_yuv);
fclose(outfile_h264);
av_log(NULL, AV_LOG_DEBUG, "end");
你好李老师,我在h264编码的时候出现了最后几秒丢失的问题,我进行了最后的洗刷编码器了,但是并不行,
这是我的编码器配置:
int open_encoder(int w, int h, AVCodecContext **enc_ctx)

{
int ret = 0;
const AVCodec *codec = avcodec_find_encoder_by_name(“libx264”);
if (!codec)
{
printf(“avcodec_find_encoder_by_name failed\n”);
return -1;
}
*enc_ctx = avcodec_alloc_context3(codec);
if (!(*enc_ctx))
{
printf(“avcodec_alloc_context3 failed\n”);
return -1;
}
printf(“start set enc_cts\n”);
// SPS PPS
(*enc_ctx)->profile = FF_PROFILE_H264_HIGH_444;
(*enc_ctx)->level = 50;
// 分辨率
(*enc_ctx)->width = w;
(*enc_ctx)->height = h;
// GOP
(*enc_ctx)->gop_size = 5;
(*enc_ctx)->keyint_min = 5; // 可选
// 设置B帧数量
(*enc_ctx)->max_b_frames = 3; // 可选
(*enc_ctx)->has_b_frames = 1; // 可选
// 设置参考帧 数量
(*enc_ctx)->refs = 3; // 可选
// 设置输入YUV格式
(*enc_ctx)->pix_fmt = AV_PIX_FMT_YUV420P;
// 设置码率
(*enc_ctx)->bit_rate = 600000; // 600bps;
// 设置帧率
(*enc_ctx)->time_base = (AVRational){1, 10}; // 帧间的间隔是time_base
(*enc_ctx)->framerate = (AVRational){10, 1}; // 每秒10帧
ret = avcodec_open2((*enc_ctx), codec, NULL);
if (ret < 0)
{
printf(“error:%d\n”, av_err2str(ret));
exit(-1);
return -1;
}
printf(“successfully open avcodec_open2 \n”);
return 0;
}
这是我的编码过程:
int encode(AVCodecContext *codec_ctx, AVFrame *avframe, AVPacket *outpkt, FILE *outfile)
{
printf(“sned frame to encoder ,pts=%lld\n”, avframe->pts);
int ret = avcodec_send_frame(codec_ctx, avframe);
if (ret < 0)
{
fprintf(stderr, “Error sending frame to encoder\n”);
return -1;
}
while (ret >= 0)
{
ret = avcodec_receive_packet(codec_ctx, outpkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
return 0;
}
else if (ret < 0)
{
printf(“Error, Failed to encode!\n”);
exit(1);
}
printf(“fwrite - outpkt.size: %d \n”, outpkt->size);
fwrite(outpkt->data, 1, outpkt->size, outfile);
fflush(outfile);
av_packet_unref(outpkt);
}
return 0;
}
我发现打印出来的数据中:
sned frame to encoder ,pts=31
[dshow @ 0000024421188440] passing through packet of type video size 1843200 timestamp 915440172873 orig timestamp 915440172873 graph timestamp 915450090000 diff 9917127 Integrated Camera
sned frame to encoder ,pts=32
[libx264 @ 00000244293e0980] frame= 0 QP=20.83 NAL=3 Slice:I Poc:0 I:3600 P:0 SKIP:0 size=22953 bytes
fwrite - outpkt.size: 22953
[dshow @ 0000024421188440] passing through packet of type video size 1843200 timestamp 915441132638 orig timestamp 915441132638 graph timestamp 915451050000 diff 9917362 Integrated Camera
sned frame to encoder ,pts=33 从我发的第32帧开始编码器才开始打印出来frame的数据,然后最后我发完之后,
sned frame to encoder ,pts=99
[libx264 @ 00000244293e0980] frame= 67 QP=20.33 NAL=2 Slice:B Poc:4 I:44 P:991 SKIP:2565 size=2672 bytes
fwrite - outpkt.size: 2672
[dshow @ 0000024421188440] passing through packet of type video size 1843200 timestamp 915507371689 orig timestamp 915507371689 graph timestamp 915517280000 diff 9908311 Integrated Camera
sned frame to encoder ,pts=100
[libx264 @ 00000244293e0980] frame= 68 QP=21.20 NAL=0 Slice:B Poc:2 I:0 P:740 SKIP:2860 size=1266 bytes
fwrite - outpkt.size: 1266
[dshow @ 0000024421188440] passing through packet of type video size 1843200 timestamp 915508331366 orig timestamp 915508331366 graph timestamp 915518240000 diff 9908634 Integrated Camera
[dshow @ 0000024421188440] passing through packet of type video size 1843200 timestamp 915509293200 orig timestamp 915509293200 graph timestamp 915519200000 diff 9906800 Integrated Camera
发完了100帧之后,貌似编码器只处理了68帧,这个时候后面好像并没有继续编码了,这是什么情况呢?

正在回答 回答被采纳积分+3

插入代码

1回答

李超 2025-03-20 22:52:27

在while 循环之后再做一次send_frame...,传入的数据为0,表示将缓冲区里的数据输出,然后再通过receive_packet...接受编码后的帧,再写到文件里就好了。之所以少几秒是因为编码器缓冲区里的数据没输出

0 回复 有任何疑惑可以回复我~
  • 提问者 慕后端2131159 #1
    我找到问题了,原来是我encode函数里面,第一句打印了frame的参数,然后最后一次输出编码器缓冲区的时候,传入的是NULL,导致最后解码崩溃了,不过并没有报错
    回复 有任何疑惑可以回复我~ 2025-03-21 08:20:56
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号