在通用平台应用上使用mediacapture类,我试图在录制中添加叠加效果。叠加效果在预览中正常工作,如果我在开始记录之前设置效果,则可以进行录制。如果我尝试在录制期间设置效果,系统会生成异常:"为媒体类型指定的数据无效,不一致或不受此对象支持#34;。什么会导致它仅在活动记录会话期间失败?
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;
我使用固定的VideoStabilization效果运行程序,没有任何问题,因此它似乎与使用自定义类有关。我也包括它。没有编译错误或警告,并使用Win2D包。
C ++ Effect Class
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");
}
};
我在C#中编写了一个简单的例子并在我的开发机器上进行了尝试,并且对于为媒体类型指定的&#34;数据失败的方式相同...&#34;信息。然后我把程序放在另一台机器上,它工作得很好????我为Cpu而不是Gpu设置了效果,因此在运行相同的4.6框架的平台上表现不同是没有意义的。以下是测试计划TestVideoApp2
的链接我发现了一些有关此问题的其他信息。看来输入流设置为YUY2。我把它更改为NV12,它开始工作了。不幸的是,我改变了相机,即使新相机支持这种输出格式,它也因无效的媒体类型而失败。它似乎与输入媒体类型与效果支持的媒体类型有关。不确定这里的关系是什么,但正在取得一些进展。也许有人知道视频输入与效果媒体类型应该是什么才能正常工作。
好的,似乎我必须在输入帧中将输入格式从相机(YUY2或NV12)更改为ARGB32,并在退出时可能返回NV12,并将YUY2或NV12设置为支持的类型。失败的是支持的效果媒体类型是ARGB32,并且正在击中录制的NV12媒体流输入过滤器类型。这听起来合理吗?是否有更直接的方法,因为这可能会非常痛苦。
通过将效果的输入格式设置为YUY2然后通过SoftwareBitmap.Convert将其转换为BGR8,我找到了解决问题的方法。从那里我通过像素字节数组手动完成效果,然后在从ProcessFrame返回之前转换回YUY2。这似乎现在工作正常。不幸的是,我不能使用Win2D,因为它不支持YUY2。我想要一个GPU解决方案,但目前CPU解决方案似乎解决了我的迫切需求。也许其他人可能能够使用GPU提出解决方案。