video_recorder.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "video_recorder.h"
  2. #include "avrecorder/capturer/video/VideoCaptureManager.h"
  3. #include <Windows.h>
  4. #include <capturer/finder.h>
  5. using namespace avrecorder::video;
  6. bool VideoRecorder::Open(HWND srcHwnd, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method)
  7. {
  8. CaptureTarget target;
  9. target.type = CaptureTargetType::Window;
  10. target.hwnd = srcHwnd;
  11. RECT clientRect;
  12. if (!GetClientRect(srcHwnd, &clientRect))
  13. return false;
  14. int width = clientRect.right - clientRect.left;
  15. int height = clientRect.bottom - clientRect.top;
  16. _capturer.open(target, method, width, height);
  17. return _Open(param);
  18. }
  19. bool VideoRecorder::Open(int monitorIdx,
  20. Encoder<MediaType::VIDEO>::Param& param,
  21. CaptureMethod method)
  22. {
  23. CaptureTarget target;
  24. target.type = CaptureTargetType::Monitor;
  25. target.monitorIdx = monitorIdx;
  26. auto monitorInfo = MonitorFinder::GetList()[monitorIdx];
  27. RECT rect = monitorInfo.rect;
  28. int width = rect.right - rect.left;
  29. int height = rect.bottom - rect.top;
  30. _capturer.open(target, method, width, height);
  31. return _Open(param);
  32. }
  33. bool VideoRecorder::_Open(Encoder<MediaType::VIDEO>::Param& param)
  34. {
  35. __CheckBool(_encodeFrame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_NV12,
  36. _capturer.getFrame()
  37. ? _capturer.getFrame()->width
  38. : param.width,
  39. _capturer.getFrame()
  40. ? _capturer.getFrame()->height
  41. : param.height));
  42. {
  43. std::lock_guard<std::mutex> renderLk(_renderMtx);
  44. __CheckBool(_renderFrame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_NV12,
  45. _capturer.getFrame()
  46. ? _capturer.getFrame()->width
  47. : param.width,
  48. _capturer.getFrame()
  49. ? _capturer.getFrame()->height
  50. : param.height));
  51. }
  52. // 捕获定时器和帧获取逻辑
  53. _captureTimer.Start(param.fps, [this] {
  54. auto srcFrame = _capturer.getFrame();
  55. if (srcFrame != nullptr) {
  56. std::lock_guard<std::mutex> muxLk(__mtx);
  57. if (srcFrame->format != _encodeFrame->format) {
  58. std::lock_guard<std::mutex> renderLk(_renderMtx);
  59. Free(_encodeFrame, [this] { av_frame_free(&_encodeFrame); });
  60. __CheckNo(
  61. _encodeFrame = Frame<MediaType::VIDEO>::Alloc(AVPixelFormat(srcFrame->format),
  62. srcFrame->width,
  63. srcFrame->height));
  64. }
  65. av_frame_copy(_encodeFrame, srcFrame);
  66. }
  67. });
  68. param.width = _capturer.getFrame() ? _capturer.getFrame()->width : param.width;
  69. param.height = _capturer.getFrame() ? _capturer.getFrame()->height : param.height;
  70. _param = param;
  71. return true;
  72. }
  73. AVFrame* VideoRecorder::GetRenderFrame()
  74. {
  75. std::lock_guard<std::mutex> renderLk(_renderMtx);
  76. if (_encodeFrame == nullptr) {
  77. return nullptr;
  78. }
  79. if (_renderFrame->format != _encodeFrame->format) {
  80. Free(_renderFrame, [this] { av_frame_free(&_renderFrame); });
  81. _renderFrame = Frame<MediaType::VIDEO>::Alloc(AVPixelFormat(_encodeFrame->format),
  82. _encodeFrame->width,
  83. _encodeFrame->height);
  84. }
  85. av_frame_copy(_renderFrame, _encodeFrame);
  86. return _renderFrame;
  87. }
  88. bool VideoRecorder::LoadMuxer(AvMuxer& muxer)
  89. {
  90. _muxer = &muxer;
  91. __CheckBool((_streamIndex = muxer.AddVideoStream(_param)) != -1);
  92. return true;
  93. }
  94. bool VideoRecorder::StartRecord()
  95. {
  96. _totalPts = 0;
  97. _lossPts = 0;
  98. _lossHistory.clear();
  99. _muxTimer.Start(_param.fps, [this] {
  100. ++_totalPts;
  101. bool loss = !_muxer->Write(_encodeFrame, _streamIndex);
  102. if (loss)
  103. ++_lossPts;
  104. _lossHistory.push_back(loss);
  105. if (_lossHistory.size() > LOSS_WINDOW)
  106. _lossHistory.pop_front();
  107. });
  108. _isRecord = true;
  109. return true;
  110. }
  111. void VideoRecorder::StopRecord()
  112. {
  113. _isRecord = false;
  114. _muxTimer.Stop();
  115. }
  116. double VideoRecorder::GetLossRate()
  117. {
  118. if (_lossHistory.size() < LOSS_WINDOW)
  119. return -1.0; // 统计中
  120. int lossCount = std::count(_lossHistory.begin(), _lossHistory.end(), true);
  121. return double(lossCount) / _lossHistory.size();
  122. }
  123. void VideoRecorder::Close()
  124. {
  125. StopRecord();
  126. _captureTimer.Stop();
  127. _capturer.close();
  128. Free(_encodeFrame, [this] { av_frame_free(&_encodeFrame); });
  129. Free(_renderFrame, [this] { av_frame_free(&_renderFrame); });
  130. }
  131. void VideoRecorder::SetCaptureSource(HWND srcHwnd, CaptureMethod method)
  132. {
  133. // 只切换采集源,不重启编码器和推流
  134. CaptureTarget target;
  135. target.type = CaptureTargetType::Window;
  136. target.hwnd = srcHwnd;
  137. RECT clientRect;
  138. if (!GetClientRect(srcHwnd, &clientRect))
  139. return;
  140. int width = clientRect.right - clientRect.left;
  141. int height = clientRect.bottom - clientRect.top;
  142. _capturer.open(target, method, width, height);
  143. }
  144. void VideoRecorder::SetCaptureSource(int monitorIdx, CaptureMethod method)
  145. {
  146. // 只切换采集源,不重启编码器和推流
  147. CaptureTarget target;
  148. target.type = CaptureTargetType::Monitor;
  149. target.monitorIdx = monitorIdx;
  150. auto monitorInfo = MonitorFinder::GetList()[monitorIdx];
  151. RECT rect = monitorInfo.rect;
  152. int width = rect.right - rect.left;
  153. int height = rect.bottom - rect.top;
  154. _capturer.open(target, method, width, height);
  155. }