美文网首页
H264视频文件如何缩放分辨率

H264视频文件如何缩放分辨率

作者: glumes | 来源:发表于2022-03-21 09:54 被阅读0次

    前几天在知识星球里面有位朋友请教问题:如何将 H264 视频缩放分辨率?

    具体的问题详情如下:

    image

    将 800x600 的 H264 文件缩放成 400x300 的,大概的流程是先解码,得到 AVFrame 后对其做缩放操作,然后再编码,得到 AVPacket 后写入文件即可。

    思路没错的话,就可以看看这位同学的写法了,截取部分代码:

    image

    大家一起来挑错,看看遇到问题一般解决思路是什么样的。

    问题一

    首先提问者一直在 av_parser_parse2 函数处报错。

    遇到这种情况不要慌,必现的问题先断点一下看看输入参数是否正确。

    IDE 的断点调试是常见操作了,工程师进阶必备。

    我没有调试提问者的代码,但也怀疑输入参数 pkt 有异常,顺着代码往下看,果然在函数最末尾几行调用了 av_packet_free 方法。

    一般通过 av_packet_alloc 去申请 AVPacket ,而 av_packet_free 就是直接释放并置 nullptr ,这样下次在执行 av_parser_parse2 方法肯定就挂了。

    void av_packet_free(AVPacket **pkt)
    {
        if (!pkt || !*pkt)
            return;
    
        av_packet_unref(*pkt);
        av_freep(pkt);
    }
    

    所以这里肯定有问题呀。

    问题二

    接着看其他问题,想要缩放分辨率,可以代码截图中并没有看到任何缩放的代码,直接将解码后的 AVFrame 送去编码就可以缩放吗?

    我猜想,提问者应该在设置编码的 AVCodecContext 时就已经指定好了缩放后的分辨率 400x300 ,但送去编码的 AVFrame 还是 800x600 的,这样编码的结果会是缩放的吗?

    经过试验证明,编码的视频确实是 400x300 的,但画面却是从 800x600 截取的一部分,并没有显示完全,所以这样是不能起到缩放效果的。

    要缩放还是得用 FFmpeg 中 SwsContext 提供的方法。

    // 初始化
    swsCtx = sws_getContext(800,600,AV_PIX_FMT_YUV420P,400,300,AV_PIX_FMT_YUV420P,SWS_BILINEAR, nullptr, nullptr,nullptr);
    // 缩放
    sws_scale(swsCtx,decodeFrame->data,decodeFrame->linesize,0,decodeFrame->height,encodeFrame->data,encodeFrame->linesize);
    

    将缩放后的 AVFrame 送去编码就可以得到正确的效果了。

    问题三

    再仔细看提问者的代码,有必要在解码 avcodec_receive_frame 之前调用 av_frame_make_writable 吗?

    由于提问者的代码本身不对,其实也不用调用 av_frame_make_writable 的,正常的缩放应该要两个 AVFrame 的,解码的 AVFrame 不需要,反而编码的 AVFrame 需要保证可写。

    以上就是关于这次提问的一些问题反馈了,我自己也实现了一个简单的 H264 视频文件缩放分辨率的例子,完整的代码就放在知识星球里

    相关文章

      网友评论

          本文标题:H264视频文件如何缩放分辨率

          本文链接:https://www.haomeiwen.com/subject/hrbzdrtx.html