Direct3D设备管理器(Direct3D device manager)

  这几天在做dxva2硬件加速,找不到什么资料,翻译了一下微软的两篇相关文档。并准备记录一下用ffmpeg实现dxva2,将在第三篇写到。这是第一篇,英文原址:https://msdn.microsoft.com/en-us/library/aa965267(v=vs.85).aspx 

  Direct3D设备管理器(Direct3D device manager)允许两个或多个对象(object)共用同一个Direct3D 9 设备(device)。其中一个对象作为Direct3D 9 设备的拥有者。要能共享设备,拥有设备的对象(the owner)要创建Direct3D设备管理器,其他对象可以获得一个指向这个设备管理器的指针,然后通过设备管理器获得一个指向Direct3D 设备的指针。每个使用这个设备的的对象都有一个互斥锁,防止与其他设备同时使用这个设备。(我的注释:即一次只能有一个对象使用设备,不能两个对象同时使用同一个设备。这就是锁的互斥功能)

注意:Direct3D 设备管理器只支持Direct3D 9 设备。不支持DXGI 设备.

    要创建Direct3D 设备管理器, 需要调用DXVA2CreateDirect3DDeviceManager9函数。这个函数返回一个指向这个创建的设备管理器的IDirect3DDeviceManager9接口的指针,以及一个重置标志(reset token)。重置标志使得使用Direct3D 设备的对象能够通过这个设备管理器设置(或重置)设备。调用IDirect3DDeviceManager9::ResetDevice函数以初始化设备管理器,传入Direct3D设备的指针和重置标志(这句翻译的不好,就是把这两个参数传给函数来初始化设备,看下面的代码就会明白)。

以下代码展示如何创建和初始化设备管理器。

HRESULT CreateD3DDeviceManager(
    IDirect3DDevice9 *pDevice, 
    UINT *pReset, 
    IDirect3DDeviceManager9 **ppManager
    )
{
    UINT resetToken = 0;

    IDirect3DDeviceManager9 *pD3DManager = NULL;

    HRESULT hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &pD3DManager);

    if (FAILED(hr))
    {
        goto done;
    }

    hr = pD3DManager->ResetDevice(pDevice, resetToken);

    if (FAILED(hr))
    {
        goto done;
    }

    *ppManager = pD3DManager;
    (*ppManager)->AddRef();

    *pReset = resetToken;


done:
    SafeRelease(&pD3DManager);
    return hr;
}

拥有设备的对象必须给其他对象提供一种获得IDirect3DDeviceManager9接口指针的方式。标准机制是实现IMFGetService接口。改服务的GUID是MR_VIDEO_ACCELERATION_SERVICE。

    要在多个对象中共用设备,每个对象(包括拥有设备的对象)必须通过设备管理器去获得设备,如下:

(1)调用IDirect3DDeviceManager9::OpenDeviceHandle函数获取设备句柄。

(2)要想使用设备,调用IDirect3DDeviceManager9::LockDevice并传入设备句柄。该方法返回一个指向IDirect3DDevice9 接口的指针。该方法能以阻塞和非阻塞两种模式调用,取决于fBlock参数的值。

(3)用完设备后,应调用IDirect3DDeviceManager9::UnlockDevice。这样其他对象就可以使用这个设备了。

(4)退出前,调用IDirect3DDeviceManager9::CloseDeviceHandle关闭设备句柄。

    你应当只在使用设备的时候才设置设备锁(the device lock),因为设置设备锁会阻止其他对象使用设备。(我的注释:这一点如果有疑惑,百度一下互斥锁的定义就会明白了,就是一个防止多个对象同时使用同一个设备导致混乱的互斥机制)

    拥有设备的对象(the ownder)可以通过调用ResetDevice函数在任意时候切换到其他设备,特别地,在原始设备丢失的情况下。设备丢失可以由各种原因造成,包括改变显示器分辨率,电源管理操作,锁定或解锁电脑,等等。更多情况,请转Direct3D文档。

    ResetDevice函数会把任何之前打开的设备句柄置为无效。设备无效后,LockDevice函数返回DXVA2_E_NEW_VIDEO_DEVICE。如果发生这种情况,关闭句柄并再次调用OpenDeviceHandle以重新获得新的设备句柄,如以下代码锁展示的。

下面的例子展示了如何打开设备句柄和锁设备(lock the device)。

HRESULT LockDevice(
    IDirect3DDeviceManager9 *pDeviceManager,
    BOOL fBlock,
    IDirect3DDevice9 **ppDevice, // Receives a pointer to the device.
    HANDLE *pHandle              // Receives a device handle.   
    )
{
    *pHandle = NULL;
    *ppDevice = NULL;

    HANDLE hDevice = 0;

    HRESULT hr = pDeviceManager->OpenDeviceHandle(&hDevice);

    if (SUCCEEDED(hr))
    {
        hr = pDeviceManager->LockDevice(hDevice, ppDevice, fBlock);
    }

    if (hr == DXVA2_E_NEW_VIDEO_DEVICE)
    {
        // Invalid device handle. Try to open a new device handle.
        hr = pDeviceManager->CloseDeviceHandle(hDevice);

        if (SUCCEEDED(hr))
        {
            hr = pDeviceManager->OpenDeviceHandle(&hDevice);
        }

        // Try to lock the device again.
        if (SUCCEEDED(hr))
        {
            hr = pDeviceManager->LockDevice(hDevice, ppDevice, TRUE); 
        }
    }

    if (SUCCEEDED(hr))
    {
        *pHandle = hDevice;
    }
    return hr;
}

转载于:https://www.cnblogs.com/betterwgo/p/6124588.html

很抱歉,作为AI语言模型,我无法编写实际的安卓应用程序。但我可以给您一些基本的指导和思路,帮助您了解如何连接WIFI-Direct。 首先,您需要在Android应用程序中实现WIFI-Direct连接的基本功能。这包括以下步骤: 1. 检查设备是否支持WIFI-Direct。您可以使用WifiP2pManager类来检查设备是否支持WIFI-Direct,如下所示: ``` WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); if (manager != null && manager.isWifiP2pSupported()) { // WIFI-Direct is supported } else { // WIFI-Direct is not supported } ``` 2. 初始化WIFI-Direct。您需要创建一个WifiP2pManager对象和一个WifiP2pManager.Channel对象,用于与WIFI-Direct框架进行通信。您可以在Activity的onCreate()方法中执行此操作,如下所示: ``` WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); WifiP2pManager.Channel channel = manager.initialize(this, getMainLooper(), null); ``` 3. 执行WIFI-Direct扫描。您可以使用WifiP2pManager.discoverPeers()方法执行WIFI-Direct扫描,以查找其他设备。您可以在Activity中创建一个BroadcastReceiver对象,以侦听WIFI-Direct扫描结果。您需要在AndroidManifest.xml文件中添加以下权限: ``` <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> ``` 以下是执行WIFI-Direct扫描的示例代码: ``` manager.discoverPeers(channel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { // WIFI-Direct discovery started successfully } @Override public void onFailure(int reason) { // WIFI-Direct discovery failed } }); // Create a BroadcastReceiver for WIFI-Direct scan results private BroadcastReceiver wifiDirectReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { // WIFI-Direct peers changed WifiP2pDeviceList devices = intent.getParcelableExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST); // Get a list of available devices and update the UI accordingly } } }; // Register the BroadcastReceiver to receive WIFI-Direct scan results IntentFilter filter = new IntentFilter(); filter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); registerReceiver(wifiDirectReceiver, filter); ``` 4. 连接到其他设备。一旦您发现了其他WIFI-Direct设备,您可以使用WifiP2pManager.connect()方法连接到它们。您需要在Activity中创建一个BroadcastReceiver对象,以侦听连接状态更改。以下是连接到其他设备的示例代码: ``` WifiP2pConfig config = new WifiP2pConfig(); config.deviceAddress = device.deviceAddress; manager.connect(channel, config, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { // WIFI-Direct connection started successfully } @Override public void onFailure(int reason) { // WIFI-Direct connection failed } }); // Create a BroadcastReceiver for WIFI-Direct connection status changes private BroadcastReceiver connectionReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { // WIFI-Direct connection status changed NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO); if (networkInfo.isConnected()) { // Connected to a WIFI-Direct device } else { // Disconnected from a WIFI-Direct device } } } }; // Register the BroadcastReceiver to receive WIFI-Direct connection status changes IntentFilter filter = new IntentFilter(); filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); registerReceiver(connectionReceiver, filter); ``` 以上是连接WIFI-Direct的基本步骤。当然,实际的应用程序可能需要更多的功能和用户界面元素,但这些步骤可以帮助您了解如何使用WIFI-Direct连接设备。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值