This commit is contained in:
lxmou666 2021-01-04 18:33:34 +08:00
parent a63abac88a
commit 11e2abe241
4 changed files with 149 additions and 87 deletions

View File

@ -228,14 +228,16 @@ namespace JianGongYun.TRTC.Components
} }
} }
//public event Action<WriteableBitmap> OnRenderVideoFrameHandler;
/// <summary> /// <summary>
/// 渲染回调int width, int height, int rotation,WriteableBitmap image /// 渲染回调byte[] data,int width, int height
/// </summary> /// </summary>
public event Action<WriteableBitmap> OnRenderVideoFrameHandler; public event Action<byte[], int, int> OnRenderVideoFrameHandler;
public event Action OnViewRemove; public event Action OnViewRemove;
private void RenderFillMode(DrawingContext dc, byte[] data, int width, int height, int rotation) private void RenderFillMode(DrawingContext dc, byte[] data, int width, int height, int rotation)
{ {
OnRenderVideoFrameHandler?.Invoke(data, width, height);
int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight; int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight;
PixelFormat pixelFormat = PixelFormats.Pbgra32; PixelFormat pixelFormat = PixelFormats.Pbgra32;
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8; int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
@ -250,17 +252,6 @@ namespace JianGongYun.TRTC.Components
mWriteableBitmap.AddDirtyRect(mInt32Rect); mWriteableBitmap.AddDirtyRect(mInt32Rect);
mWriteableBitmap.Unlock(); mWriteableBitmap.Unlock();
//var tt = ConvertWriteableBitmapToBitmapImage(mWriteableBitmap);
//OpenCvSharp.Mat result = OpenCvSharp.Extensions.BitmapConverter.ToMat(tt);
//tt.Dispose();
//result.Create(mWriteableBitmap.PixelHeight, mWriteableBitmap.PixelWidth, OpenCvSharp.MatType.CV_8UC4, 4);
//mWriteableBitmap.CopyPixels(Int32Rect.Empty, result.Data, data.Length, 4);
//LiveClassroom.bbb.Enqueue(result);
//result.ImWrite($"d:\\{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.png");
//var a = ConvertWriteableBitmapToBitmapImage(mWriteableBitmap);
//a.Save($"d:\\{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.png");
OnRenderVideoFrameHandler?.Invoke(mWriteableBitmap);
ImageBrush brush = new ImageBrush(mWriteableBitmap); ImageBrush brush = new ImageBrush(mWriteableBitmap);
if (rotation > 0) if (rotation > 0)
{ {
@ -280,6 +271,7 @@ namespace JianGongYun.TRTC.Components
private void RenderFitMode(DrawingContext dc, byte[] data, int width, int height, int rotation) private void RenderFitMode(DrawingContext dc, byte[] data, int width, int height, int rotation)
{ {
OnRenderVideoFrameHandler?.Invoke(data, width, height);
int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight; int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight;
PixelFormat pixelFormat = PixelFormats.Pbgra32; PixelFormat pixelFormat = PixelFormats.Pbgra32;
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8; int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
@ -287,9 +279,6 @@ namespace JianGongYun.TRTC.Components
if (mWriteableBitmap == null || mWriteableBitmap.PixelWidth != width || mWriteableBitmap.PixelHeight != height) if (mWriteableBitmap == null || mWriteableBitmap.PixelWidth != width || mWriteableBitmap.PixelHeight != height)
{ {
mWriteableBitmap = new WriteableBitmap(width, height, 96, 96, pixelFormat, null); mWriteableBitmap = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
//Mat result = new Mat();
//result.Create(mWriteableBitmap.PixelHeight, mWriteableBitmap.PixelWidth, MatType.CV_8U, 4);
//mWriteableBitmap.CopyPixels(Int32Rect.Empty, result.Data, (int)result.Step() * result.Rows, (int)result.Step());
mInt32Rect = new Int32Rect(0, 0, width, height); mInt32Rect = new Int32Rect(0, 0, width, height);
} }
mWriteableBitmap.Lock(); mWriteableBitmap.Lock();
@ -297,7 +286,7 @@ namespace JianGongYun.TRTC.Components
mWriteableBitmap.AddDirtyRect(mInt32Rect); mWriteableBitmap.AddDirtyRect(mInt32Rect);
mWriteableBitmap.Unlock(); mWriteableBitmap.Unlock();
OnRenderVideoFrameHandler?.Invoke(mWriteableBitmap); //OnRenderVideoFrameHandler?.Invoke(mWriteableBitmap);
ImageBrush brush = new ImageBrush(mWriteableBitmap); ImageBrush brush = new ImageBrush(mWriteableBitmap);
if (rotation > 0) if (rotation > 0)

View File

@ -47,8 +47,18 @@ namespace JianGongYun.TRTC
private static LiveWindowViewModel liveWinMode; private static LiveWindowViewModel liveWinMode;
public static ClassroomEntity CurrentClassroomEntity { get; private set; } public static ClassroomEntity CurrentClassroomEntity { get; private set; }
public static TRTCCloudCallback TRTCCloudCallback = new TRTCCloudCallback(); public static TRTCCloudCallback TRTCCloudCallback = new TRTCCloudCallback();
/// <summary>
//private static ConcurrentBag<Task> VedioRecords = new ConcurrentBag<Task>(); /// 摄像头帧
/// </summary>
public static VideoFrameEntity MainFrame = new VideoFrameEntity();
/// <summary>
/// 屏幕帧
/// </summary>
public static VideoFrameEntity SubFrame = new VideoFrameEntity();
/// <summary>
/// 背景帧
/// </summary>
public static Mat BackgroundFrame = null;
//public static int UserCount = 999; //public static int UserCount = 999;
/// <summary> /// <summary>
/// 进入直播教室 /// 进入直播教室
@ -154,7 +164,21 @@ namespace JianGongYun.TRTC
var view = AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, true); var view = AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, true);
if (liveWinMode.IsLive) if (liveWinMode.IsLive)
{ {
VedioRecordTask(view, TRTCVideoStreamType.TRTCVideoStreamTypeBig); //Stopwatch sw = new Stopwatch();
//VideoRecordTask(view, TRTCVideoStreamType.TRTCVideoStreamTypeBig);
view.OnRenderVideoFrameHandler += (data, w, h) =>
{
//sw.Restart();
lock (MainFrame)
{
MainFrame.Width = w;
MainFrame.Height = h;
MainFrame.Data = new byte[data.Length];
Buffer.BlockCopy(data, 0, MainFrame.Data, 0, data.Length);
}
//sw.Stop();
//Debug.Print("main" + sw.ElapsedMilliseconds.ToString());
};
} }
return view; return view;
} }
@ -191,7 +215,21 @@ namespace JianGongYun.TRTC
var view = AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeSub, true); var view = AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeSub, true);
if (liveWinMode.IsLive) if (liveWinMode.IsLive)
{ {
VedioRecordTask(view, TRTCVideoStreamType.TRTCVideoStreamTypeSub); //Stopwatch sw = new Stopwatch();
//VideoRecordTask(view, TRTCVideoStreamType.TRTCVideoStreamTypeSub);
view.OnRenderVideoFrameHandler += (data, w, h) =>
{
//sw.Restart();
lock (SubFrame)
{
SubFrame.Width = w;
SubFrame.Height = h;
SubFrame.Data = new byte[data.Length];
Buffer.BlockCopy(data, 0, SubFrame.Data, 0, data.Length);
}
//sw.Stop();
//Debug.Print("sub" + sw.ElapsedMilliseconds.ToString());
};
} }
return view; return view;
} }
@ -270,77 +308,94 @@ namespace JianGongYun.TRTC
} }
public static void VedioRecordTask(TXLiteAVVideoView view, TRTCVideoStreamType streamType) public static void VideoRecordTask(ref Action onEnd)
{ {
var end = false; var end = false;
Stopwatch sw1 = new Stopwatch(); onEnd = () =>
Stopwatch sw2 = new Stopwatch();
ConcurrentQueue<Mat> bitmaps = new ConcurrentQueue<Mat>();
view.OnRenderVideoFrameHandler += (b) =>
{
sw1.Restart();
bitmaps.Enqueue(b.ToMat());
sw1.Stop();
//Debug.Print("a" + sw1.Elapsed.TotalMilliseconds.ToString());
};
view.OnViewRemove += () =>
{ {
end = true; end = true;
BackgroundFrame?.Dispose();
BackgroundFrame = null;
}; };
var task = Task.Factory.StartNew(() => var resolution = settingWindowViewModel.MainEncParams.videoResolution.ToString().Split('_');//屏幕分辨率
{ var fps = settingWindowViewModel.LiveFps;
Console.WriteLine($"VedioRecordTask Start {streamType}"); BackgroundFrame = new Mat(int.Parse(resolution[1]), int.Parse(resolution[2]), MatType.CV_8UC3, Scalar.FromRgb(0x20, 0x20, 0x20));
var _recoderDir = RecoderDir;
var imgTemp = Path.Combine(_recoderDir, $"{streamType}.png"); //Stopwatch sw1 = new Stopwatch();
var videoFile = Path.Combine(_recoderDir, $"{Util.TimeStr()}_{streamType}.avi"); //Stopwatch sw2 = new Stopwatch();
VideoWriter vw = new VideoWriter(); //ConcurrentQueue<Mat> bitmaps = new ConcurrentQueue<Mat>();
bool videoWriterInit = false; //view.OnRenderVideoFrameHandler += (b) =>
var frameCount = 0; //{
Timer timer = new Timer((a) => // sw1.Restart();
{ // bitmaps.Enqueue(b.ToMat());
//Console.WriteLine($"{streamType} fps {frameCount}"); // sw1.Stop();
Debug.Print($"{streamType} fps {frameCount}"); // //Debug.Print("a" + sw1.Elapsed.TotalMilliseconds.ToString());
Interlocked.Exchange(ref frameCount, 0); //};
}, null, 0, 1000); ////view.OnRenderVideoFrameHandler1 += (a, b, c) =>
while (!end || bitmaps.Count > 0) ////{
{ //// var bb = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(a[0]) * a.Length);
if (bitmaps.Count == 0) //// System.Runtime.InteropServices.Marshal.Copy(a, 0, bb, a.Length);
{ //// var mat = new Mat(c, b, MatType.CV_32SC4, bb);
Thread.Sleep(100); //// mat.SaveImage("1.bmp");
continue; ////};
} ////view.OnViewRemove += () =>
if (bitmaps.TryDequeue(out var mat)) ////{
{ //// end = true;
sw2.Restart(); ////};
//mat.SaveImage(imgTemp); //var task = Task.Factory.StartNew(() =>
//{
// Console.WriteLine($"VideoRecordTask Start {streamType}");
// var _recoderDir = RecoderDir;
// var imgTemp = Path.Combine(_recoderDir, $"{streamType}.png");
// var videoFile = Path.Combine(_recoderDir, $"{Util.TimeStr()}_{streamType}.avi");
// VideoWriter vw = new VideoWriter();
// bool videoWriterInit = false;
// var frameCount = 0;
// Timer timer = new Timer((a) =>
// {
// //Console.WriteLine($"{streamType} fps {frameCount}");
// Debug.Print($"{streamType} fps {frameCount}");
// Interlocked.Exchange(ref frameCount, 0);
// }, null, 0, 1000);
// while (!end || bitmaps.Count > 0)
// {
// if (bitmaps.Count == 0)
// {
// Thread.Sleep(100);
// continue;
// }
// if (bitmaps.TryDequeue(out var mat))
// {
// sw2.Restart();
// //mat.SaveImage(imgTemp);
// //mat.Dispose();
// //mat = Cv2.ImRead(imgTemp, ImreadModes.AnyColor);
// //Cv2.ImShow(streamType.ToString(), mat);
// //Cv2.WaitKey(1);
// if (!videoWriterInit)
// {
// vw.Open(videoFile, FourCC.H264, settingWindowViewModel.LiveFps, mat.Size());
// videoWriterInit = true;
// }
// vw.Write(mat);
// mat.Dispose(); // mat.Dispose();
//mat = Cv2.ImRead(imgTemp, ImreadModes.AnyColor); // Interlocked.Increment(ref frameCount);
//Cv2.ImShow(streamType.ToString(), mat); // //Debug.Print("b"+sw2.Elapsed.TotalMilliseconds.ToString());
//Cv2.WaitKey(1); // }
if (!videoWriterInit) // else
{ // {
vw.Open(videoFile, FourCC.H264, settingWindowViewModel.LiveFps, mat.Size()); // Thread.Sleep(100);
videoWriterInit = true; // }
} // }
vw.Write(mat); // vw?.Release();
mat.Dispose(); // vw?.Dispose();
Interlocked.Increment(ref frameCount); // if (File.Exists(imgTemp))
//Debug.Print("b"+sw2.Elapsed.TotalMilliseconds.ToString()); // {
} // File.Delete(imgTemp);
else // }
{ // timer.Dispose();
Thread.Sleep(100); // Console.WriteLine($"VideoRecordTask End {streamType}");
} //}, TaskCreationOptions.LongRunning);
}
vw?.Release();
vw?.Dispose();
if (File.Exists(imgTemp))
{
File.Delete(imgTemp);
}
timer.Dispose();
Console.WriteLine($"VedioRecordTask End {streamType}");
}, TaskCreationOptions.LongRunning);
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace JianGongYun.TRTC.Models
{
public class VideoFrameEntity
{
public byte[] Data { get; set; } = null;
public int Width { get; set; } = 0;
public int Height { get; set; } = 0;
}
}

View File

@ -119,6 +119,7 @@ namespace JianGongYun.TRTC.Windows
{ {
var btn = sender as AduFlatButton; var btn = sender as AduFlatButton;
var start = Convert.ToBoolean(btn.Tag); var start = Convert.ToBoolean(btn.Tag);
Action onEnd = default;
if (start)//开始直播 if (start)//开始直播
{ {
if (SettingWindowViewModel.DiskSize <= ViewModels.SettingWindowViewModel.DiskWarningSize) if (SettingWindowViewModel.DiskSize <= ViewModels.SettingWindowViewModel.DiskWarningSize)
@ -157,12 +158,14 @@ namespace JianGongYun.TRTC.Windows
} }
LiveClassroom.StartMic(); LiveClassroom.StartMic();
LiveClassroom.SetMicMute(false); LiveClassroom.SetMicMute(false);
LiveClassroom.VideoRecordTask(ref onEnd);//启动录制
}, SettingWindowViewModel.ScreenRecordingCountdown); }, SettingWindowViewModel.ScreenRecordingCountdown);
} }
else else
{ {
LiveWindowViewModel.IsLive = start; LiveWindowViewModel.IsLive = start;
onEnd?.Invoke();
//停止直播 //停止直播
LiveClassroom.StopMic(); LiveClassroom.StopMic();
LiveClassroom.StopVideoMain(AfterLiveViewWrap); LiveClassroom.StopVideoMain(AfterLiveViewWrap);