如何将接收到的 Argb32VideoFrame(或 I420AVideoFrame)从 Webrtc 更改为 Texture2D?
How to change received Argb32VideoFrame(or I420AVideoFrame) from Webrtc to Texture2D?
我在 webrtc 测试中有一个问题。 (客户对客户)
从Direct3D获取的截屏帧是通过webrtc方式传输的
(Sender)
_screenShareSource = ExternalVideoTrackSource.CreateFromArgb32Callback(FrameCallback);
var videoTrackConfig = new LocalVideoTrackInitConfig { trackName = "screen_track" };
_localVideoTrack = LocalVideoTrack.CreateFromSource(_screenShareSource, videoTrackConfig);
_videoTransceiver = _peerConnection.AddTransceiver(MediaKind.Video);
_videoTransceiver.LocalVideoTrack = _localVideoTrack;
_videoTransceiver.DesiredDirection = Transceiver.Direction.SendReceive;
(Receiver)
_peerConnection.VideoTrackAdded += (RemoteVideoTrack track) =>
{
_remoteVideoTrack = track;
**_remoteVideoTrack.Argb32VideoFrameReady += _remoteVideoTrack_Argb32VideoFrameReady;
// or _remoteVideoTrack.I420AVideoFrameReady += _remoteVideoTrack_I420AVideoFrameReady;**
};
接收帧成功
private void _remoteVideoTrack_Argb32VideoFrameReady(Argb32VideoFrame frame)
{
if (frame.width != lastWidthSize ||
frame.height != lastHeigthSize)
{
//newSize = true;
lastWidthSize = frame.width;
lastHeigthSize = frame.height;
swapChain.ResizeBuffers(
2,
(int)lastWidthSize,
(int)lastHeigthSize,
SharpDX.DXGI.Format.B8G8R8A8_UNorm,
SharpDX.DXGI.SwapChainFlags.None);
}
using (var backBuffer = swapChain.GetBackBuffer<SharpDX.Direct3D11.Texture2D>(0))
using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(UpdateImage(frame)))
{
d3dDevice.ImmediateContext.CopyResource(bitmap, backBuffer);
}
swapChain.Present(0, SharpDX.DXGI.PresentFlags.None);
}
所以,我想用Direct3D把它显示在屏幕上,但我不知道怎么做。
如何将Argb32VideoFrame(或I420AVideoFrame)改为Texture2D?
或者...有没有办法在当前环境下在屏幕上显示Argb32VideoFrame(或者I420AVideoFrame)?
- 测试环境:Win10、C#(.netframework/.netcore desktop)
这是将位图更改为 Texture2D 的方法之一。
public SharpDX.Direct3D11.Texture2D CreateTexture2DFromBitmap(Argb32VideoFrame frame)
{
var width = (int)frame.width;
var height = (int)frame.height;
var stride = (int)frame.stride;
SharpDX.Direct3D11.Texture2DDescription desc = new SharpDX.Direct3D11.Texture2DDescription
{
Width = width,
Height = height,
ArraySize = 1,
BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource,
Usage = SharpDX.Direct3D11.ResourceUsage.Default,
CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None,
Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
MipLevels = 1,
OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None,
SampleDescription = new SharpDX.DXGI.SampleDescription { Count = 1, Quality = 0 }
};
using (Bitmap bitmap = new Bitmap(width, height, stride, PixelFormat.Format32bppPArgb, frame.data))
{
BitmapData bmData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
SharpDX.DataBox data = new SharpDX.DataBox(bmData.Scan0, bmData.Stride, 0);
SharpDX.DataRectangle rect = new SharpDX.DataRectangle(data.DataPointer, data.RowPitch);
SharpDX.Direct3D11.Texture2D _texture = new SharpDX.Direct3D11.Texture2D(d3dDevice, desc, new[] { rect });
bitmap.UnlockBits(bmData);
return _texture;
}
}
我在 webrtc 测试中有一个问题。 (客户对客户) 从Direct3D获取的截屏帧是通过webrtc方式传输的
(Sender)
_screenShareSource = ExternalVideoTrackSource.CreateFromArgb32Callback(FrameCallback);
var videoTrackConfig = new LocalVideoTrackInitConfig { trackName = "screen_track" };
_localVideoTrack = LocalVideoTrack.CreateFromSource(_screenShareSource, videoTrackConfig);
_videoTransceiver = _peerConnection.AddTransceiver(MediaKind.Video);
_videoTransceiver.LocalVideoTrack = _localVideoTrack;
_videoTransceiver.DesiredDirection = Transceiver.Direction.SendReceive;
(Receiver)
_peerConnection.VideoTrackAdded += (RemoteVideoTrack track) =>
{
_remoteVideoTrack = track;
**_remoteVideoTrack.Argb32VideoFrameReady += _remoteVideoTrack_Argb32VideoFrameReady;
// or _remoteVideoTrack.I420AVideoFrameReady += _remoteVideoTrack_I420AVideoFrameReady;**
};
接收帧成功
private void _remoteVideoTrack_Argb32VideoFrameReady(Argb32VideoFrame frame)
{
if (frame.width != lastWidthSize ||
frame.height != lastHeigthSize)
{
//newSize = true;
lastWidthSize = frame.width;
lastHeigthSize = frame.height;
swapChain.ResizeBuffers(
2,
(int)lastWidthSize,
(int)lastHeigthSize,
SharpDX.DXGI.Format.B8G8R8A8_UNorm,
SharpDX.DXGI.SwapChainFlags.None);
}
using (var backBuffer = swapChain.GetBackBuffer<SharpDX.Direct3D11.Texture2D>(0))
using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(UpdateImage(frame)))
{
d3dDevice.ImmediateContext.CopyResource(bitmap, backBuffer);
}
swapChain.Present(0, SharpDX.DXGI.PresentFlags.None);
}
所以,我想用Direct3D把它显示在屏幕上,但我不知道怎么做。
如何将Argb32VideoFrame(或I420AVideoFrame)改为Texture2D?
或者...有没有办法在当前环境下在屏幕上显示Argb32VideoFrame(或者I420AVideoFrame)?
- 测试环境:Win10、C#(.netframework/.netcore desktop)
这是将位图更改为 Texture2D 的方法之一。
public SharpDX.Direct3D11.Texture2D CreateTexture2DFromBitmap(Argb32VideoFrame frame)
{
var width = (int)frame.width;
var height = (int)frame.height;
var stride = (int)frame.stride;
SharpDX.Direct3D11.Texture2DDescription desc = new SharpDX.Direct3D11.Texture2DDescription
{
Width = width,
Height = height,
ArraySize = 1,
BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource,
Usage = SharpDX.Direct3D11.ResourceUsage.Default,
CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None,
Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
MipLevels = 1,
OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None,
SampleDescription = new SharpDX.DXGI.SampleDescription { Count = 1, Quality = 0 }
};
using (Bitmap bitmap = new Bitmap(width, height, stride, PixelFormat.Format32bppPArgb, frame.data))
{
BitmapData bmData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
SharpDX.DataBox data = new SharpDX.DataBox(bmData.Scan0, bmData.Stride, 0);
SharpDX.DataRectangle rect = new SharpDX.DataRectangle(data.DataPointer, data.RowPitch);
SharpDX.Direct3D11.Texture2D _texture = new SharpDX.Direct3D11.Texture2D(d3dDevice, desc, new[] { rect });
bitmap.UnlockBits(bmData);
return _texture;
}
}