以下内容来自公众号“ Fun With FFmpeg”的分享。
有朋友问:“ffmpeg的decoder解码出来的frame是不是不能直接修改data的内容?”
提出此问,说明两件事:
- 他有性能优化的意识:尝试直接修改数据,一方面省一半内存,一方面速度更快。如果不考虑性能优化,直接copy完事。
- 他发现直接修改解码输出的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是否还在用作参考帧呢?
- 码流本身的参考结构,比如是否为低延迟参考结构,是否使用长期参考帧等。
- 多线程帧级并行解码的线程数:线程数越多,延迟越高,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 举报,一经查实,本站将立刻删除。