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