我一直在使用 FFmpeg.AutoGen https://github.com/Ruslan-B/FFmpeg.AutoGen包装器解码我的 H264 视频有一段时间取得了巨大成功,现在必须添加 AAC 音频解码(以前我为此使用 G711 和 NAudio)。
我有使用 avcodec_decode_audio4 的 AAC 流解码,但是输出缓冲区或帧是浮点格式 FLT,我需要它在 S16 中。为此,我发现使用 swr_convert 和 FFmpeg.AutoGen 的非托管示例确实具有此函数 P/Invoked as;
[DllImport(SWRESAMPLE_LIBRARY, EntryPoint="swr_convert", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int swr_convert(SwrContext* s, byte** @out, int out_count, byte** @in, int in_count);
我的问题是我找不到一种成功的方法来将我的托管字节 [] 转换/修复/转换为字节** 以将其作为目标缓冲区提供。
以前有人这样做过吗?
我的非工作代码...
packet.ResetBuffer(m_avFrame->linesize[0]*2);
fixed (byte* pData = packet.Payload)
{
byte** src = &m_avFrame->data_0;
//byte** dst = *pData;
IntPtr d = new IntPtr(pData);
FFmpegInvoke.swr_convert(m_pConvertContext, (byte**)d.ToPointer(), packet.Length, src, (int)m_avFrame->linesize[0]);
}
感谢您的帮助。
干杯
戴夫
最佳答案
您尝试调用的函数记录在此处:http://www.ffmpeg.org/doxygen/2.0/swresample_8c.html#a81af226d8969df314222218c56396f6a
out_arg
参数声明如下:
uint8_t* out_arg[SWR_CH_MAX]
这是一个长度为 SWR_CH_MAX
的字节数组数组。您的翻译将其呈现为 byte**
并因此强制您使用不安全的代码。我个人认为我会避免这种情况。我会这样声明参数:
[MarshalAs(UnmanagedType.LPArray)]
IntPtr[] out_arg
像这样声明数组:
IntPtr[] out_arg = new IntPtr[channelCount];
我猜测 SWR_CH_MAX
中的 CH
是 channel 的缩写。
然后你需要为输出缓冲区分配内存。我不确定你想怎么做。您可以为每个 channel 分配一个字节数组并固定这些数组以获取一个指针以传递给 native 代码。那将是我的首选方法,因为返回时您的 channel 将位于漂亮的托管数组中。另一种方法是调用 Marshal.AllocHGlobal
。
输入缓冲区需要以相同的方式处理。
我不会使用您当前使用的自动 pinvoke 翻译。看来他会执意要强制你使用指针和不安全的代码。没有太大帮助。我会手译。
很抱歉没有提供更具体的细节,但这有点难,因为您的问题不包含有关代码示例中使用的类型的任何信息。我希望一般的建议是有用的。
关于c# - 如何从托管字节 [] 缓冲区获取字节**,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23058044/