ffmpeg - libavcodec 中的 write_back_intra_pred_mode() 函数有什么作用?

标签 ffmpeg h.264 libavcodec

Bellow 是 libavcodec/h264.h 中定义的 ffmpeg 中的一个函数:

static av_always_inline void write_back_intra_pred_mode(const H264Context *h,
                                                        H264SliceContext *sl)
{
    int8_t *i4x4       = sl->intra4x4_pred_mode + h->mb2br_xy[sl->mb_xy];
    int8_t *i4x4_cache = sl->intra4x4_pred_mode_cache;

    AV_COPY32(i4x4, i4x4_cache + 4 + 8 * 4);
    i4x4[4] = i4x4_cache[7 + 8 * 3];
    i4x4[5] = i4x4_cache[7 + 8 * 2];
    i4x4[6] = i4x4_cache[7 + 8 * 1];
}

这个函数有什么作用?

你能解释一下函数体吗?

最佳答案

该函数更新帧内预测模式的帧宽缓存(以 4x4 block 分辨率),位于变量 sl->intra4x4_pred_mode 中。每片或 h->intra4x4_pred_mode对于整个框架。此缓存稍后用于 h264_mvpred.h ,特别是函数fill_decode_caches()绕线510-528 ,设置上下文(左/上邻居) block 信息,用于解码位于当前 4x4 block 集下方或右侧的后续 4x4 block 。

[编辑]

好的,更多关于变量设计的内容在这里。 sl->mb_xy 是 sl->mb_x + sl->mb_y * mb_stride。将 mb_stride 视为图像宽度(以 mbs 为单位)的填充版本。所以 mb_xy 是当前宏 block 的光栅有序索引。一些变量以 block (4x4) 而非宏 block (16x16) 分辨率进行索引,因此要在单位之间进行转换,请使用 mb2br_xy。这应该可以解释帧宽缓存的布局(intra4x4_pred_mode/i4x4)。

现在,本地每个宏 block 缓存,它包含当前宏 block 的 4x4 条目,加上左/上边缘条目,所以 5x5。然而,在一条 lea 指令中,乘以 5 需要 2 个寄存器,而 8 只需要一个,所以我们更喜欢 8(更一般地说,我们更喜欢 2 的幂)。所以分辨率变成8(width)x5(height),总共40个entry,其中每行左边3个是未使用的,第4个是左边,右边4个是当前宏 block 的实际entry。顶行在上面,下面的4行是当前宏 block 的实际条目。

因此,从缓存到帧宽缓存的备份使用 8 作为步幅,4/3/2/1 作为 y=3/2/1/0 的索引,4-7 作为 x=0-3 的索引。在 backcopy 中,您会注意到我们实际上并没有复制整个 4x4 block ,而只是复制了最后一行(AVCOPY32 复制了 4 个条目,offset=4[y=3]+8[stride]*4[x=0] ) 和其他每一行的最右侧条目 (7[x=3]+8[stride]*1-3[y=0-2])。这是因为只有右/下边缘作为 future 宏 block 解码的上/左上下文是有趣的,所以其余的都是不必要的。

如图所示,i4x4_pred_mode_cache 的布局为:

x x x TL T0 T1 T2 T3
x x x L0 00 01 02 03
x x x L1 10 11 12 13
x x x L2 20 21 22 23
x x x L3 30 31 32 33

x 表示未使用,TL 是左上角,Ln 是左[n],Tn 是上[n],编号条目 ab 是 y=a,x=b,对于 16x16 宏 block 中的 4x4 block 。

你可能想知道为什么TL放在[3]而不是[0],即为什么不是TL T0-3 x x x (其余行依此类推);原因是在帧范围和 block 本地缓存中,T0-3(和 00-03、10-13、20-23、30-33)是 4 字节对齐的 4 种模式集,这意味着在大多数机器上,在一条指令 (COPY32) 中复制 4 个条目要快得多。如果我们做了一个未对齐的副本,这会增加额外的开销并(稍微)减慢解码速度。

关于ffmpeg - libavcodec 中的 write_back_intra_pred_mode() 函数有什么作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34738979/

相关文章:

ffmpeg - 如何成功使用ffmpeg将图像转换为视频

c++ - 使用opencv进行视频处理的音频输出

ffmpeg - 如何使用 ffmpeg 将 flv 文件发布到 `real time` 中的 RTMP 服务器?

c++ - 我可以在流式传输/写入时同时读取 mp4 文件的较早部分吗?

ffmpeg - "copy"在 ffmpeg 命令行中做了什么?

ios - ffmpeg 在 iOS 中将 wma 转换为 mp3

javascript - H264 视频使用 src 属性工作。使用 MediaSource API (Chromium) 时同一视频失败

windows - 在 .NET 上使用 H.264 编码网络摄像头帧

ffmpeg - 解码 MP3,然后增加音频音量,然后对新音频进行编码

android - 在 android ffmpeg 库上设置 maxrate 的正确方法是什么?