FFmpeg解码出来的frame data可以修改吗?

以下内容来自公众号“ Fun With FFmpeg”的分享。

有朋友问:“ffmpeg的decoder解码出来的frame是不是不能直接修改data的内容?”

提出此问,说明两件事:

  1. 他有性能优化的意识:尝试直接修改数据,一方面省一半内存,一方面速度更快。如果不考虑性能优化,直接copy完事。
  2. 他发现直接修改解码输出的frame data会出问题。

他发现直接修改frame data有问题,所以答案是“不能”吗?答案是“看情况”。

换一种问法,怎么判断FFmpeg解码输出的frame data可写?什么情况下frame data可写?

判断frame data可写的方法:

int av_frame_is_writable(AVFrame *frame);

是不是有种恍然大悟的感觉,像是脑筋急转弯一样?看FFmpeg API多简单明了。很多人说FFmpeg API太复杂费解,因为业务逻辑确实复杂,简单的API照顾不过来多样化的usecase。每一个API已经是尽力去简化了,除非无法再简化。

用互联网黑话来追问,它的底层逻辑是什么?怎么判断出可写的?

答案是:检查frame data的引用计数,当引用计数为1时可写,也就是说,你是frame的唯一持有者时,可写。除此之外,还有一个readonly的判定,是硬件解码输出的frame data本身是readonly状态。以下讨论忽略硬件解码的情况。

引入计数为1时可写,逻辑顺理成章,frame只归你管,想搞啥搞啥。接下来的追问是,什么情况下引用计数不为1?

答案是,当它作为参考帧位于参考帧列表里的时候。如果你修改了frame data,会导致拿它做参考帧的视频帧解码输出画面异常。有哪些因素决定某一个frame是否还在用作参考帧呢

  1. 码流本身的参考结构,比如是否为低延迟参考结构,是否使用长期参考帧等。
  2. 多线程帧级并行解码的线程数:线程数越多,延迟越高,frame在参考帧列表的概率越低。

现在知道了frame data是否可写,那么对于不可写的frame,怎么处理呢?手动拷贝一份?No!

/**
 * Ensure that the frame data is writable, avoiding data copy if possible.
 *
 * Do nothing if the frame is writable, allocate new buffers and copy the data
 * if it is not. Non-refcounted frames behave as non-writable, i.e. a copy
 * is always made.
 *
 * @return 0 on success, a negative AVERROR on error.
 *
 * @see av_frame_is_writable(), av_buffer_is_writable(),
 * av_buffer_make_writable()
 */
int av_frame_make_writable(AVFrame *frame);

用make_writable API,连手动判断是否可写的步骤都省了:可写的frame它直接返回,不可写给你拷贝一份。

原文:https://mp.weixin.qq.com/s/u2c1FjS1eT0vitisUZV2FQ

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论