- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用 Media Foundation 的 Source Reader 编写硬件加速的 h264 解码器,但遇到了一个问题。我关注了this tutorial并使用 Windows SDK Media Foundation 示例支持我自己。
当硬件加速关闭时,我的应用似乎可以正常运行,但它无法提供我需要的性能。当我通过将 IMFDXGIDeviceManager
传递给用于创建读取器的 IMFAttributes
来打开加速时,事情变得复杂了。
如果我使用 D3D_DRIVER_TYPE_NULL
驱动程序创建 ID3D11Device
,应用程序运行良好并且帧处理速度比在软件模式下更快,但由 CPU 和 GPU 判断使用它仍然在 CPU 上完成大部分处理。
另一方面,当我使用 D3D_DRIVER_TYPE_HARDWARE
驱动程序创建 ID3D11Device
并运行应用程序时,可能会发生以下四种情况之一。
在 IMFMediaBuffer::Lock
函数返回 0x887a0005 之前,我只得到不可预测数量的帧(通常为 1-3),它被描述为“GPU 设备实例已暂停。使用 GetDeviceRemovedReason
以确定适当的操作”。当我调用 ID3D11Device::GetDeviceRemovedReason
时,我得到 0x887a0020,它被描述为“驱动程序遇到问题并被置于设备已删除状态”,这并没有我希望的那么有用。
应用程序在调用 IMFMediaBuffer::Lock
时在外部 dll 中崩溃。似乎 dll 取决于所使用的 GPU。对于 Intel 集成 GPU,它是 igd10iumd32.dll,对于 Nvidia 移动 GPU,它是 mfplat.dll。此特定崩溃的消息如下:“在 decoder_tester.exe 中的 0x53C6DB8C (mfplat.dll) 处抛出异常:0xC0000005:访问冲突读取位置 0x00000024”。执行过程中的地址不同,有时涉及读取,有时涉及写入。
图形驱动程序停止响应,系统短时间挂起,然后应用程序崩溃(如第 2 点)或完成(如第 1 点)。
该应用运行良好,并使用硬件加速处理所有帧。
大部分时间是 1 或 2,很少是 3 或 4。
下面是在我的机器(Intel Core i5-6500 和 HD Graphics 530,Windows 10 Pro)上以不同模式进行处理时 CPU/GPU 使用率的情况。
我在三台机器上测试了该应用程序。它们都配备了英特尔集成 GPU(HD 4400、HD 4600、HD 530)。其中之一还具有可切换的 Nvidia 专用 GPU (GF 840M)。它对所有这些都具有相同的行为,唯一的区别是当使用 Nvidia 的 GPU 时它会在不同的 dll 中崩溃。
我以前没有使用 COM 或 DirectX 的经验,但所有这些都是不一致且不可预测的,因此对我来说它看起来像是内存损坏。不过,我不知道我在哪里犯了错误。你能帮我找出我做错了什么吗?
我能想出的最小代码示例如下。我正在使用 Visual Studio Professional 2015 将其编译为 C++ 项目。我准备了启用硬件加速的定义并选择了硬件驱动程序。将它们注释掉以改变行为。此外,代码需要 this video file出现在项目目录中。
#include <iostream>
#include <string>
#include <atlbase.h>
#include <d3d11.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <windows.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mfreadwrite.lib")
#pragma comment(lib, "mfuuid.lib")
#define ENABLE_HW_ACCELERATION
#define ENABLE_HW_DRIVER
void handle_result(HRESULT hr)
{
if (SUCCEEDED(hr))
return;
WCHAR message[512];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), message, ARRAYSIZE(message), nullptr);
printf("%ls", message);
abort();
}
int main(int argc, char** argv)
{
handle_result(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
handle_result(MFStartup(MF_VERSION));
{
CComPtr<IMFAttributes> attributes;
handle_result(MFCreateAttributes(&attributes, 3));
#if defined(ENABLE_HW_ACCELERATION)
CComPtr<ID3D11Device> device;
D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0 };
#if defined(ENABLE_HW_DRIVER)
handle_result(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
levels, ARRAYSIZE(levels), D3D11_SDK_VERSION, &device, nullptr, nullptr));
#else
handle_result(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_NULL, nullptr, D3D11_CREATE_DEVICE_SINGLETHREADED,
levels, ARRAYSIZE(levels), D3D11_SDK_VERSION, &device, nullptr, nullptr));
#endif
UINT token;
CComPtr<IMFDXGIDeviceManager> manager;
handle_result(MFCreateDXGIDeviceManager(&token, &manager));
handle_result(manager->ResetDevice(device, token));
handle_result(attributes->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, manager));
handle_result(attributes->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE));
handle_result(attributes->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE));
#else
handle_result(attributes->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE));
#endif
CComPtr<IMFSourceReader> reader;
handle_result(MFCreateSourceReaderFromURL(L"Rogue One - A Star Wars Story - Trailer.mp4", attributes, &reader));
CComPtr<IMFMediaType> output_type;
handle_result(MFCreateMediaType(&output_type));
handle_result(output_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
handle_result(output_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32));
handle_result(reader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, nullptr, output_type));
unsigned int frame_count{};
std::cout << "Started processing frames" << std::endl;
while (true)
{
CComPtr<IMFSample> sample;
DWORD flags;
handle_result(reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
0, nullptr, &flags, nullptr, &sample));
if (flags & MF_SOURCE_READERF_ENDOFSTREAM || sample == nullptr)
break;
std::cout << "Frame " << frame_count++ << std::endl;
CComPtr<IMFMediaBuffer> buffer;
BYTE* data;
handle_result(sample->ConvertToContiguousBuffer(&buffer));
handle_result(buffer->Lock(&data, nullptr, nullptr));
// Use the frame here.
buffer->Unlock();
}
std::cout << "Finished processing frames" << std::endl;
}
MFShutdown();
CoUninitialize();
return 0;
}
最佳答案
你的代码在概念上是正确的,唯一的评论 - 而且不是很明显 - 媒体基础解码器是多线程的。您正在为它提供单线程版本的 Direct3D 设备。您必须解决这个问题,否则您会得到当前的结果:访问冲突和卡住,这是未定义的行为。
// NOTE: No single threading
handle_result(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
(0 * D3D11_CREATE_DEVICE_SINGLETHREADED) | D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
levels, ARRAYSIZE(levels), D3D11_SDK_VERSION, &device, nullptr, nullptr));
// NOTE: Getting ready for multi-threaded operation
const CComQIPtr<ID3D11Multithread> pMultithread = device;
pMultithread->SetMultithreadProtected(TRUE);
另请注意,这个简单的代码示例在您为获取连续缓冲区而添加的代码行周围存在性能瓶颈。显然,访问数据是您的举动……但是设计的行为是解码数据已经在视频内存中,而您向系统内存的传输是一项昂贵的操作。也就是说,您对循环造成了严重的性能损失。您将有兴趣以这种方式检查数据的有效性,并且当涉及到性能基准测试时,您应该将其注释掉。
关于c++ - 如何正确使用硬件加速的 Media Foundation Source Reader 来解码视频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40913196/
我对此很陌生,我在这里的论坛上检查过答案,但我没有找到任何真正可以帮助我的答案。我正在尝试播放 res/raw 文件夹中的视频。到目前为止我已经设置了这段代码: MediaPlayer mp; @Ov
我可以播放一个视频剪辑,检测视频的结尾,然后创建一个表单,然后播放另一个视频剪辑。我的问题是,表单 react 不正确,我创建了带有提交按钮和两个单选按钮可供选择的表单。我希望让用户进行选择,验证响应
首先,我必须说我在web2py讨论组中看到过类似的内容,但我不太理解。 我使用 web2py 设置了一个数据库驱动的网站,其中的条目只是 HTML 文本。其中大多数将包含 img和/或video指向相
我正在尝试在视频 View 中播放 YouTube 视频。 我将 xml 布局如下: 代码是这样的: setContentView(R.layout.webview); VideoV
我正在开发一个需要嵌入其中的 youtube 视频播放器的 android 应用程序。我成功地从 API 获得了 RTSP 视频 URL,但是当我试图在我的 android 视频 View 中加载这个
我目前正在从事一个使用 YouTube API 的网络项目。 我完全不熟悉 API。所以每一行代码都需要付出很多努力。 使用以下代码,我可以成功检索播放列表中的项目: https://www.goog
是否可以仅使用视频 ID 和 key 使用 API V3 删除 youtube 视频?我不断收到有关“必需参数:部分”丢失的错误消息。我用服务器和浏览器 api 键试了一下这是我的代码: // $yo
所以我一直坚持这个大约一个小时左右,我就是无法让它工作。到目前为止,我一直在尝试从字符串中提取整个链接,但现在我觉得只获取视频 ID 可能更容易。 RegEx 需要从以下链接样式中获取 ID/URL,
var app = angular.module('speakout', []).config( function($sceDelegateProvider) {
我正在努力从 RSS 提要中阅读音频、视频新闻。我如何确定该 rss 是用于新闻阅读器还是用于音频或视频? 这是视频源:http://feeds.cbsnews.com/CBSNewsVideo 这是
利用python反转图片/视频 准备:一张图片/一段视频 python库:pillow,moviepy 安装库 ?
我希望在用户双击视频区域时让我的视频全屏显示,而不仅仅是在他们单击控件中的小图标时。有没有办法添加事件或其他东西来控制用户点击视频时发生的情况? 谢谢! 最佳答案 按照 Musa 的建议,附
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 7年前关闭。 Improve this questi
我有一个公司培训视频加载到本地服务器上。我正在使用 HTML5 的视频播放来观看这些视频。该服务器无法访问网络,但我已加载 apache 并且端口 8080 对同一网络上的所有机器开放。 这些文件位于
我想混合来自 video.mp4 的视频(时长 1 分钟)和来自 audio.mp3 的音频(10 分钟持续时间)到一个持续时间为 1 分钟的输出文件中。来自 audio.mp3 的音频应该是从 4
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 8年前关闭。 Improve this questi
我正在尝试使用 peer/getUserMedia 创建一个视频 session 网络应用程序。 目前,当我将唯一 ID 发送到视频 session 时,我能够听到/看到任何加入我的 session
考虑到一段时间内的观看次数,我正在评估一种针对半自动脚本的不同方法,该脚本将对视频元数据执行操作。 简而言之,只要视频达到指标中的某个阈值,就说观看次数,它将触发某些操作。 现在要执行此操作,我将不得
我正在通过iBooks创建专门为iPad创建动态ePub电子书的网站。 它需要支持youtube视频播放,所以当我知道视频的直接路径时,我正在使用html5 标记。 有没有一种使用html5 标签嵌入
我对Android不熟悉,我想浏览youtube.com并在Webview内从网站显示视频。当前,当我尝试执行此操作时,将出现设备的浏览器,并让我使用设备浏览器浏览该站点。如果Webview不具备这种
我是一名优秀的程序员,十分优秀!