我有一个项目,我需要从实时网络流解码h264视频,最终得到一个纹理,我可以在iOS设备上的另一个框架(Unity3D)中显示.我可以使用VTDecompressionSession成功解码视频,然后使用CVMetalTextureCacheCreateTextureFromImage(或OpenGL变体)获取纹理.当我使用低延迟编码器并且图像缓冲器按显示顺序出现时,它工作得很好,但是,当我使用常规编码器时,图像缓冲区不按显示顺序出现,重新排序图像缓冲区显然要困难得多.我期望.
第一次尝试是使用kVTDecodeFrame_EnableAsynchronousDecompression和kVTDecodeFrame_EnableTemporalProcessing设置VTDecodeFrameFlags ...然而,事实证明VTDecompressionSession可以选择忽略该标志并做任何它想要的......在我的情况下,它选择忽略该标志并仍然输出编码器顺序的缓冲区(不是显示顺序).基本上没用.
下一次尝试是将图像缓冲区与显示时间戳相关联,然后将它们放入一个向量中,这样我就可以在创建纹理时抓取所需的图像缓冲区.问题似乎是进入与时间戳相关联的VTDecompressionSession的图像缓冲区不再是出现的相同缓冲区,从而使时间戳无效.
例如,进入解码器......
VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression;
VTDecodeInfoFlags flagOut;
// Presentation time stamp to be passed with the buffer
NSNumber *nsPts = [NSNumber numberWithDouble:pts];
VTDecompressionSessionDecodeFrame(_decompressionSession, sampleBuffer, flags,
(void*)CFBridgingRetain(nsPts), &flagOut);
Run Code Online (Sandbox Code Playgroud)
在回调方......
void decompressionSessionDecodeFrameCallback(void *decompressionOutputRefCon, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef imageBuffer, CMTime presentationTimeStamp, CMTime presentationDuration)
{
// The presentation time stamp...
// No longer seems to be associated with the buffer that it went in with!
NSNumber* pts = CFBridgingRelease(sourceFrameRefCon);
}
Run Code Online (Sandbox Code Playgroud)
订购时,回调端的时间戳按预期速率单调增加,但缓冲区的顺序不正确.有没有人在这里看到我在哪里犯错误?或者知道如何确定回调端缓冲区的顺序?在这一点上,我已经尝试了我能想到的一切.
我有一个基于Romain Guy的例子的TextureView,可以在这里找到.在Android 4.3和4.4上,经过几轮暂停和恢复应用程序后,应用程序崩溃,唯一的错误痕迹是LogCat中的致命信号11.我创建了一个测试应用程序,它使用Romain Guy的确切代码来查看它是否是我在代码中所做的事情,而Romain的代码也与致命信号11一起崩溃.
我已经确定,如果我使用Handler而不是Thread运行代码,它似乎不会使应用程序崩溃.Handler应该在主UI线程上运行(或者至少我相信它),这可能暗示它是一个线程问题.
我还确定在调用canvas.drawX(drawColor,drawBitmap,drawRect等等)期间发生了崩溃.锁定和解锁画布似乎不是问题.我怀疑线程正在被取消,而其他一些代码仍在使用画布,但由于缺少任何真正的异常并且崩溃相当不一致,我很难跟踪问题.
任何见解将不胜感激.