C++ 在通用平台应用程序上录制时的视频效果失败

C++ 在通用平台应用程序上录制时的视频效果失败,c++,uwp,C++,Uwp,在通用平台应用程序上使用mediacapture类,我试图在录音中添加叠加效果。如果我在开始录制之前设置了效果,那么覆盖效果在预览和录制时都可以很好地工作。如果我在录制期间尝试设置效果,系统会生成一个异常:“为媒体类型指定的数据无效、不一致或此对象不支持”。什么会导致它仅在活动记录会话期间失败 VideoEffectDefinition^ effect = ref new VideoEffectDefinition("CompositionEffectLibrary.Co

在通用平台应用程序上使用mediacapture类,我试图在录音中添加叠加效果。如果我在开始录制之前设置了效果,那么覆盖效果在预览和录制时都可以很好地工作。如果我在录制期间尝试设置效果,系统会生成一个异常:“为媒体类型指定的数据无效、不一致或此对象不支持”。什么会导致它仅在活动记录会话期间失败

            VideoEffectDefinition^ effect = ref new VideoEffectDefinition("CompositionEffectLibrary.CompositionEffect", props);
        if (mediaCapture->MediaCaptureSettings->VideoDeviceCharacteristic == VideoDeviceCharacteristic::AllStreamsIdentical ||
            mediaCapture->MediaCaptureSettings->VideoDeviceCharacteristic == VideoDeviceCharacteristic::PreviewRecordStreamsIdentical)
        {
            // This effect will modify both the preview and the record streams, because they are the same stream.
            create_task(mediaCapture->AddVideoEffectAsync(effect, MediaStreamType::VideoRecord))
                .then([this](IMediaExtension^ mediaExtension)
            {
            });
        }

        else
        {
            create_task(mediaCapture->AddVideoEffectAsync(effect, MediaStreamType::VideoRecord))
                .then([this, effect](IMediaExtension^ mediaExtension)
            {
                auto mediaCapture = m_mediaCaptureMgr.Get();
                create_task(mediaCapture->AddVideoEffectAsync(effect, MediaStreamType::VideoPreview))
                    .then([this](IMediaExtension^ mediaExtension)
                {
                });
            });
        } // else

    return true;
我运行的程序具有固定的视频稳定效果,没有问题,因此它似乎与使用自定义类有关。我也包括在内。没有编译错误或警告,并且使用Win2D包

C++效果类

public ref class CompositionEffect sealed : public IBasicVideoEffect
{
    CanvasDevice^ _canvasDevice = nullptr;
    CanvasBitmap^ _overlayBitmap = nullptr;
    IRandomAccessStream^ _overlayStream;
    int _offsetX;
    int _offsetY;
    int _width;
    int _height;
    bool _atTop;
    int _position;
    float _opacity;
    bool _layerCreated = false;
    CanvasActiveLayer^ _activeLayer = nullptr;
    Vector<VideoEncodingProperties^>^ _videoEncProps;

public:
    CompositionEffect()
    {
        VideoEncodingProperties^ encodingProperties = ref new VideoEncodingProperties();
        encodingProperties->Subtype = "ARGB32";
        _videoEncProps = ref new Vector<VideoEncodingProperties^>{ encodingProperties };
    }

    property bool IsReadOnly
    {
        virtual bool get() { return true; }
    }

    property IVectorView<VideoEncodingProperties^> ^SupportedEncodingProperties
    {
        virtual IVectorView<VideoEncodingProperties^> ^get() { return _videoEncProps->GetView(); }
    }

    property MediaMemoryTypes SupportedMemoryTypes
    {
        virtual MediaMemoryTypes get() { return MediaMemoryTypes::Gpu; }
    }

    property bool TimeIndependent
    {
        virtual bool get() { return true; }
    }

    // Get positional information from loaded image
    virtual void CompositionEffect::SetEncodingProperties(VideoEncodingProperties^ encodingProperties, IDirect3DDevice^ device)
    {
        if (_canvasDevice != nullptr)
            return;

        _canvasDevice = CanvasDevice::CreateFromDirect3D11Device(device);

        create_task(CanvasBitmap::LoadAsync(_canvasDevice, _overlayStream)).then([this](CanvasBitmap^ bmp)
        {
            _overlayBitmap = bmp;

            // overlay at left side of source
            if (_position == 0)
            {
                _offsetX = 0;
            }

            // overlay at right side of source
            else if (_position == 2)
            {
                _offsetX = _width - bmp->SizeInPixels.Width;
            }

            // overlay at center of source
            else
            {
                _offsetX = (_width - bmp->SizeInPixels.Width) / 2;
            }

            // Set overlay vertical position
            if (_atTop)
            {
                _offsetY = 0;
            }

            else
            {
                _offsetY = (_height - bmp->SizeInPixels.Height);
            }
        });
    }

    virtual void Close(MediaEffectClosedReason reason)
    {
    }

    virtual void DiscardQueuedFrames() { }

    // Draw overlay image over source image at specified coordinates
    virtual void ProcessFrame(ProcessVideoFrameContext^ context)
    {           

        IDirect3DSurface^ outputSurface = context->OutputFrame->Direct3DSurface;
        CanvasRenderTarget^ renderTarget = CanvasRenderTarget::CreateFromDirect3D11Surface(_canvasDevice, outputSurface);
        CanvasDrawingSession^ drawSession = renderTarget->CreateDrawingSession();
        _activeLayer = drawSession->CreateLayer(_opacity);

        if (_overlayBitmap != nullptr)
        {
            drawSession->DrawImage(_overlayBitmap, (float)_offsetX, (float)_offsetY);
        }

        delete(_activeLayer);
    }

    // Set the operational parameters of the effect
    virtual void SetProperties(IPropertySet^ configuration) 
    {
        _overlayStream = (IRandomAccessStream^)configuration->Lookup("bitmap");
        _width = (int)configuration->Lookup("width");
        _height = (int)configuration->Lookup("height");
        _opacity = (float)(int)configuration->Lookup("opacity");
        _opacity /= 100;
        _atTop = (bool)configuration->Lookup("attop");
        _position = (int)configuration->Lookup("position");
    }

};
public ref class CompositionEffect sealed:public ref class CompositionEffect
{
CanvasDevice^_CanvasDevice=nullptr;
CanvasBitmap^_overlayBitmap=nullptr;
Irandomaccesstream^上覆流;
国际抵消;
国际抵销;
内部宽度;
内部高度;
布尔阿托普;
内部位置;
浮动不透明度;
bool_layerCreated=false;
CanvasActiveLayer^_activeLayer=nullptr;
矢量投影;
公众:
复合效应()
{
VideoEncodingProperties^encodingProperties=ref新VideoEncodingProperties();
编码属性->子类型=“ARGB32”;
_videoEncProps=ref新向量{encodingProperties};
}
物业bool是只读的
{
虚拟bool get(){return true;}
}
属性IVectorView ^SupportedEncodingProperties
{
虚拟IVectorView ^get(){return\u VideoEnProps->GetView();}
}
属性MediaMemoryTypes SupportedMemoryTypes
{
虚拟MediaMemoryTypes get(){返回MediaMemoryTypes::Gpu;}
}
属性布尔时间无关
{
虚拟bool get(){return true;}
}
//从加载的图像中获取位置信息
虚拟void CompositionEffect::SetEncodingProperties(VideoEncodingProperties^ encodingProperties,IDirect3DDevice^设备)
{
如果(_canvasDevice!=nullptr)
返回;
_canvasDevice=canvasDevice::CreateFromDirect3D11设备(设备);
创建任务(CanvasBitmap::LoadAsync(_canvasDevice,_OverlyStream))。然后([this](CanvasBitmap^bmp)
{
_overlayBitmap=bmp;
//覆盖在源的左侧
如果(_位置==0)
{
_offsetX=0;
}
//覆盖在源的右侧
否则如果(_位置==2)
{
_offsetX=_width-bmp->SizeInPixels.width;
}
//叠加在源的中心
其他的
{
_offsetX=(_width-bmp->SizeInPixels.width)/2;
}
//设置叠加垂直位置
如果(_atTop)
{
_offsetY=0;
}
其他的
{
_offsetY=(_height-bmp->SizeInPixels.height);
}
});
}
虚拟无效关闭(MediaEffectClosedReason原因)
{
}
虚拟空丢弃队列框架(){}
//在指定坐标处在源图像上绘制覆盖图像
虚拟无效ProcessFrame(ProcessVideoFrameContext^上下文)
{           
IDirect3DSurface^outputSurface=context->OutputFrame->Direct3DSurface;
CanvasRenderTarget^renderTarget=CanvasRenderTarget::CreateFromDirect3D11Surface(\u canvasDevice,outputSurface);
CanvasDrawingSession^drawSession=renderTarget->CreateDrawingSession();
_activeLayer=drawSession->CreateLayer(_不透明度);
如果(_overlayBitmap!=nullptr)
{
drawSession->DrawImage(_overlayBitmap,(float)_offsetX,(float)_offsetY);
}
删除(_activeLayer);
}
//设置效果的操作参数
虚拟void集合属性(IPropertySet^配置)
{
_OverlyStream=(irandomaccesstream^)配置->查找(“位图”);
_宽度=(int)配置->查找(“宽度”);
_高度=(int)配置->查找(“高度”);
_不透明度=(浮点)(int)配置->查找(“不透明度”);
_不透明度/=100;
_atTop=(bool)配置->查找(“atTop”);
_位置=(int)配置->查找(“位置”);
}
};
我用C#编写了一个简单的示例,并在我的开发机器上进行了尝试,但失败的方式与“为媒体类型指定的数据…”消息相同。然后我把程序放在另一台机器上,它运行得很好????我为Cpu而不是Gpu设置了效果,因此在运行相同4.6框架的平台上,它的行为没有任何意义。这里是测试程序的链接

我发现了一些关于这个问题的附加信息。似乎输入流被设置为YUY2。我把它改成了NV12,它开始工作了。不幸的是,我更换了相机,尽管新相机支持这种输出格式,但由于媒体类型无效,它失败了。它似乎与效果的输入媒体类型和支持的媒体类型有关。不确定这里的关系是什么,但正在取得一些进展。也许有人知道视频输入和效果媒体类型应该是什么才能正常工作

好的,看来我必须在进程帧中将摄像头(YUY2或NV12)的输入格式更改为ARGB32,退出时可能会返回到NV12,并将YUY2或NV12设置为支持的类型。失败之处在于支持的效果媒体类型为ARGB32,并且正在命中录制的NV12媒体流输入筛选器类型。这听起来合理吗??是否有一种更直接的方法,因为这可能会非常痛苦

我找到了解决问题的方法,将效果的输入格式设置为YUY2,然后通过将其转换为BGR8