区块链技术博客
www.b2bchain.cn

百倍变速–解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!求职学习资料

本文介绍了百倍变速–解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

昨天周六,群里面还有人在技术交流!!

默默吐槽一下:这些人真卷啊,大周末还搞技术,是游戏不好玩还是电影不好看。

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

一开始是讨论剪映的 100 变速是如何实现,群主作为相关人士肯定就不方便透露这些了,不过也有其他大佬给出了思路。

讨论焦点还是围绕如何丢帧展开的。

百倍变速,比如正常速度下一帧是播放第 1s 时刻的内容,而变速后要播放 100s 时刻了。

此时的逻辑有以下几种情况:

  1. 如果下一个播放时刻要超过目前 GOP 大小了,那么就及时 seek 到离目标 pts 最近的关键帧,比如从 1s 变速后到了 100s ,那就 seek 到第 98s 。
  2. 如果下一个播放时刻在同一 GOP 内了,那就继续往下解码,判断解码后的帧 pts 不需要显示就直接丢弃再接着往后解 ,直到接近了目标时间点就显示。
  3. seek 后的时间点没达到目标时间点的情况,需要继续解码的可以重复第二步。

以上是针对群内大佬的总结,拿着小本本赶紧记下来。

此时,还有大佬对解码丢帧给出了其他意见:

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

主要是针对非参考帧的丢帧处理,也是文章的重点内容。

当我们通过 av_read_frame 得到一个 AVPacket 之后,可以判断它的 nal_ref_idc 值来决定是否要丢弃。

如果为 0 ,说明其他帧不需要参考该帧,可以直接丢弃不发送给解码器,而不是解码后再丢帧。

如果你不清楚 nal_ref_idc 是什么意思 ? 那么可以了解一下 H.264 码流 NALU 的概念。

H.264 码流传输时以 NALU 的形式进行,NALU 主要由一个字节的 HAL Header 和 RBSP 两部分组成。

HAL Header 的组成形式如下图所示:

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

HAL Header 的计算如下:

forbidden_zero_bit(1bit) + nal_ref_idc(2bit) + nal_unit_type(5bit)

nal_unit_type 不同的值代表不同类型的帧,解析 AVPacket 完全可以得到如上的信息,后面在公众号 音视频开发进阶 继续更新文章详解如何计算

所以,在解码时完全是可以丢弃这些非参考帧的,放心大胆地操作吧。

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

而且丢非参考帧的操作也是经过了产品亿级检测的,这一点我确实可以作证!!!

FFmpeg 中的丢帧

以上的丢帧逻辑是根据 H.264 规范来的,那么在 FFmpeg 的源码中有没有针对这一逻辑做处理呢?

那必然是有的啊!!!

如果仔细看 ffplay 的源码,在源码中有如下的调用方式:

“`cpp
/* this thread gets the stream from the disk or the network */
static int read_thread(void *arg)
{
// 省略部分代码
for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
enum AVMediaType type = st->codecpar->codec_type;
// AVDISCARD_ALL 抛弃所有的帧
st->discard = AVDISCARD_ALL;
if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
st_index[type] = i;
}

// 省略部分代码 if (!video_disable)     st_index[AVMEDIA_TYPE_VIDEO] =         av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,                             st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0); if (!audio_disable)     st_index[AVMEDIA_TYPE_AUDIO] =         av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,                             st_index[AVMEDIA_TYPE_AUDIO],                             st_index[AVMEDIA_TYPE_VIDEO],                             NULL, 0);  /* open the streams */ if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {     // 开启解码线程     stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]); }

昨天周六,群里面还有人在技术交流!!

默默吐槽一下:这些人真卷啊,大周末还搞技术,是游戏不好玩还是电影不好看。

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

一开始是讨论剪映的 100 变速是如何实现,群主作为相关人士肯定就不方便透露这些了,不过也有其他大佬给出了思路。

讨论焦点还是围绕如何丢帧展开的。

百倍变速,比如正常速度下一帧是播放第 1s 时刻的内容,而变速后要播放 100s 时刻了。

此时的逻辑有以下几种情况:

  1. 如果下一个播放时刻要超过目前 GOP 大小了,那么就及时 seek 到离目标 pts 最近的关键帧,比如从 1s 变速后到了 100s ,那就 seek 到第 98s 。
  2. 如果下一个播放时刻在同一 GOP 内了,那就继续往下解码,判断解码后的帧 pts 不需要显示就直接丢弃再接着往后解 ,直到接近了目标时间点就显示。
  3. seek 后的时间点没达到目标时间点的情况,需要继续解码的可以重复第二步。

以上是针对群内大佬的总结,拿着小本本赶紧记下来。

此时,还有大佬对解码丢帧给出了其他意见:

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

主要是针对非参考帧的丢帧处理,也是文章的重点内容。

当我们通过 av_read_frame 得到一个 AVPacket 之后,可以判断它的 nal_ref_idc 值来决定是否要丢弃。

如果为 0 ,说明其他帧不需要参考该帧,可以直接丢弃不发送给解码器,而不是解码后再丢帧。

如果你不清楚 nal_ref_idc 是什么意思 ? 那么可以了解一下 H.264 码流 NALU 的概念。

H.264 码流传输时以 NALU 的形式进行,NALU 主要由一个字节的 HAL Header 和 RBSP 两部分组成。

HAL Header 的组成形式如下图所示:

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

HAL Header 的计算如下:

forbidden_zero_bit(1bit) + nal_ref_idc(2bit) + nal_unit_type(5bit)

nal_unit_type 不同的值代表不同类型的帧,解析 AVPacket 完全可以得到如上的信息,后面在公众号 音视频开发进阶 继续更新文章详解如何计算

所以,在解码时完全是可以丢弃这些非参考帧的,放心大胆地操作吧。

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

而且丢非参考帧的操作也是经过了产品亿级检测的,这一点我确实可以作证!!!

FFmpeg 中的丢帧

以上的丢帧逻辑是根据 H.264 规范来的,那么在 FFmpeg 的源码中有没有针对这一逻辑做处理呢?

那必然是有的啊!!!

如果仔细看 ffplay 的源码,在源码中有如下的调用方式:

“`cpp
/* this thread gets the stream from the disk or the network */
static int read_thread(void *arg)
{
// 省略部分代码
for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
enum AVMediaType type = st->codecpar->codec_type;
// AVDISCARD_ALL 抛弃所有的帧
st->discard = AVDISCARD_ALL;
if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
st_index[type] = i;
}

// 省略部分代码 if (!video_disable)     st_index[AVMEDIA_TYPE_VIDEO] =         av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,                             st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0); if (!audio_disable)     st_index[AVMEDIA_TYPE_AUDIO] =         av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,                             st_index[AVMEDIA_TYPE_AUDIO],                             st_index[AVMEDIA_TYPE_VIDEO],                             NULL, 0);  /* open the streams */ if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {     // 开启解码线程     stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]); }

昨天周六,群里面还有人在技术交流!!

默默吐槽一下:这些人真卷啊,大周末还搞技术,是游戏不好玩还是电影不好看。

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

一开始是讨论剪映的 100 变速是如何实现,群主作为相关人士肯定就不方便透露这些了,不过也有其他大佬给出了思路。

讨论焦点还是围绕如何丢帧展开的。

百倍变速,比如正常速度下一帧是播放第 1s 时刻的内容,而变速后要播放 100s 时刻了。

此时的逻辑有以下几种情况:

  1. 如果下一个播放时刻要超过目前 GOP 大小了,那么就及时 seek 到离目标 pts 最近的关键帧,比如从 1s 变速后到了 100s ,那就 seek 到第 98s 。
  2. 如果下一个播放时刻在同一 GOP 内了,那就继续往下解码,判断解码后的帧 pts 不需要显示就直接丢弃再接着往后解 ,直到接近了目标时间点就显示。
  3. seek 后的时间点没达到目标时间点的情况,需要继续解码的可以重复第二步。

以上是针对群内大佬的总结,拿着小本本赶紧记下来。

此时,还有大佬对解码丢帧给出了其他意见:

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

主要是针对非参考帧的丢帧处理,也是文章的重点内容。

当我们通过 av_read_frame 得到一个 AVPacket 之后,可以判断它的 nal_ref_idc 值来决定是否要丢弃。

如果为 0 ,说明其他帧不需要参考该帧,可以直接丢弃不发送给解码器,而不是解码后再丢帧。

如果你不清楚 nal_ref_idc 是什么意思 ? 那么可以了解一下 H.264 码流 NALU 的概念。

H.264 码流传输时以 NALU 的形式进行,NALU 主要由一个字节的 HAL Header 和 RBSP 两部分组成。

HAL Header 的组成形式如下图所示:

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

HAL Header 的计算如下:

forbidden_zero_bit(1bit) + nal_ref_idc(2bit) + nal_unit_type(5bit)

nal_unit_type 不同的值代表不同类型的帧,解析 AVPacket 完全可以得到如上的信息,后面在公众号 音视频开发进阶 继续更新文章详解如何计算

所以,在解码时完全是可以丢弃这些非参考帧的,放心大胆地操作吧。

百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!

而且丢非参考帧的操作也是经过了产品亿级检测的,这一点我确实可以作证!!!

FFmpeg 中的丢帧

以上的丢帧逻辑是根据 H.264 规范来的,那么在 FFmpeg 的源码中有没有针对这一逻辑做处理呢?

那必然是有的啊!!!

如果仔细看 ffplay 的源码,在源码中有如下的调用方式:

“`cpp
/* this thread gets the stream from the disk or the network */
static int read_thread(void *arg)
{
// 省略部分代码
for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
enum AVMediaType type = st->codecpar->codec_type;
// AVDISCARD_ALL 抛弃所有的帧
st->discard = AVDISCARD_ALL;
if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
st_index[type] = i;
}

// 省略部分代码 if (!video_disable)     st_index[AVMEDIA_TYPE_VIDEO] =         av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,                             st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0); if (!audio_disable)     st_index[AVMEDIA_TYPE_AUDIO] =         av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,                             st_index[AVMEDIA_TYPE_AUDIO],                             st_index[AVMEDIA_TYPE_VIDEO],                             NULL, 0);  /* open the streams */ if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {     // 开启解码线程     stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]); }

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 百倍变速–解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!!求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们