将 SSE 指令与 Libavcodec 一起使用

Use of SSE instructions along side with Libavcodec

我编写了一个简单的视频会议应用程序,它使用多线程进行视频和音频混合。我使用 libavcodec (ffmpeg) 编解码器来混合视频。据我所知,libavcodec 使用 SSE 指令来实现高性能。对于音频混合,我使用的是一种简单的混合算法,它只添加样本。我已经用 C++ 中的简单 for 循环编写了加法算法,但现在我想使用 SSE 指令对其进行优化,如下所示:

__m128i* d = (__m128i*) pOutBuffer;
__m128i* s = (__m128i*) pInBuffer;
for (DWORD n = (DWORD)(nSizeToMix + 7) >> 3; n != 0; --n, ++d, ++s)
{
    //Load data in SSE registers
    __m128i xmm1 = _mm_load_si128(d);
    __m128i xmm2 = _mm_load_si128(s);
    //SSE2 sum
    _mm_store_si128(d, _mm_add_epi16(xmm1, xmm2));
}

音频混合是与视频混合同时在一个单独的线程中完成的。当我使用 SSE 指令时,应用程序突然崩溃在与混音无关的位置,在 encoding/decoding 视频中。

好像因为libavcodec使用了SSE寄存器和指令,所以我的代码和它有冲突。有什么方法可以在不与 libvcodec (ffmpeg) 冲突的情况下使用 SSE 指令吗?任何建议表示赞赏。

只要您使用的是现代编译器(10 年以上)并且您不使用汇编代码,上下文切换就应该没问题。编译器知道其目标平台的 ABI,因此您不必知道。

如果您包含了导致应用程序崩溃的确切代码,最可能的原因是对齐问题。将 _mm_load_si128 替换为 _mm_loadu_si128,将 _mm_store_si128 替换为 _mm_storeu_si128,看看是否有帮助。

更新 1: 另一个可能的原因是 SSE 版本完成得太快,这会触发并发错误。尝试添加例如Sleep( 2 ) 在循环后调用,如果视频可以正常工作,则意味着您需要修复跨线程推送或拉取数据的代码。

更新 2: 正如 Alan 所指出的,数组(缓冲区)的大小可能不是 16 字节的倍数 (16 * (nSizeToMix + 7) / 8)。这肯定会导致您的应用程序崩溃或内存损坏。