#include "video_recorder.h" #include "avrecorder/capturer/video/VideoCaptureManager.h" #include #include #include #include #include using namespace avrecorder::video; bool VideoRecorder::Open(HWND srcHwnd, Encoder::Param& param, CaptureMethod method) { CaptureTarget target; target.type = CaptureTargetType::Window; target.hwnd = srcHwnd; RECT clientRect; if (!GetClientRect(srcHwnd, &clientRect)) return false; int width = clientRect.right - clientRect.left; int height = clientRect.bottom - clientRect.top; _capturer.open(target, method, width, height); return _Open(param); } bool VideoRecorder::Open(int monitorIdx, Encoder::Param& param, CaptureMethod method) { CaptureTarget target; target.type = CaptureTargetType::Monitor; target.monitorIdx = monitorIdx; auto monitorInfo = MonitorFinder::GetList()[monitorIdx]; RECT rect = monitorInfo.rect; int width = rect.right - rect.left; int height = rect.bottom - rect.top; _capturer.open(target, method, width, height); return _Open(param); } bool VideoRecorder::_Open(Encoder::Param& param) { __CheckBool(_encodeFrame = Frame::Alloc(AV_PIX_FMT_NV12, _capturer.getFrame() ? _capturer.getFrame()->width : param.width, _capturer.getFrame() ? _capturer.getFrame()->height : param.height)); { std::lock_guard renderLk(_renderMtx); __CheckBool(_renderFrame = Frame::Alloc(AV_PIX_FMT_NV12, _capturer.getFrame() ? _capturer.getFrame()->width : param.width, _capturer.getFrame() ? _capturer.getFrame()->height : param.height)); } // 捕获定时器和帧获取逻辑 _captureTimer.Start(param.fps, [this] { auto srcFrame = _capturer.getFrame(); if (srcFrame != nullptr) { std::lock_guard muxLk(__mtx); if (srcFrame->format != _encodeFrame->format) { std::lock_guard renderLk(_renderMtx); Free(_encodeFrame, [this] { av_frame_free(&_encodeFrame); }); __CheckNo( _encodeFrame = Frame::Alloc(AVPixelFormat(srcFrame->format), srcFrame->width, srcFrame->height)); } av_frame_copy(_encodeFrame, srcFrame); } }); param.width = _capturer.getFrame() ? _capturer.getFrame()->width : param.width; param.height = _capturer.getFrame() ? _capturer.getFrame()->height : param.height; _param = param; return true; } AVFrame* VideoRecorder::GetRenderFrame() { std::lock_guard renderLk(_renderMtx); if (_encodeFrame == nullptr) { return nullptr; } if (_renderFrame->format != _encodeFrame->format) { Free(_renderFrame, [this] { av_frame_free(&_renderFrame); }); _renderFrame = Frame::Alloc(AVPixelFormat(_encodeFrame->format), _encodeFrame->width, _encodeFrame->height); } av_frame_copy(_renderFrame, _encodeFrame); return _renderFrame; } bool VideoRecorder::LoadMuxer(AvMuxer& muxer) { std::lock_guard lock(_muxersMtx); // 检查是否已经加载过这个muxer for (const auto& info : _muxers) { if (info.muxer == &muxer) { qDebug() << "VideoRecorder::LoadMuxer: Muxer already loaded, streamIndex:" << info.streamIndex; return true; // 已经加载过,直接返回成功 } } qDebug() << "VideoRecorder::LoadMuxer: Adding video stream with params - name:" << QString::fromStdString(_param.name) << "width:" << _param.width << "height:" << _param.height << "fps:" << _param.fps << "bitRate:" << _param.bitRate; int streamIndex = muxer.AddVideoStream(_param); if (streamIndex == -1) { qDebug() << "VideoRecorder::LoadMuxer: Failed to add video stream to muxer"; return false; } qDebug() << "VideoRecorder::LoadMuxer: Successfully added video stream, streamIndex:" << streamIndex; _muxers.emplace_back(&muxer, streamIndex); return true; } bool VideoRecorder::UnloadMuxer(AvMuxer& muxer) { std::lock_guard lock(_muxersMtx); auto it = std::find_if(_muxers.begin(), _muxers.end(), [&muxer](const MuxerInfo& info) { return info.muxer == &muxer; }); if (it != _muxers.end()) { _muxers.erase(it); return true; } return false; // 没有找到对应的muxer } bool VideoRecorder::StartRecord() { std::lock_guard lock(_muxersMtx); if (_muxers.empty()) { return false; // 没有加载任何muxer } _totalPts = 0; _lossPts = 0; { std::lock_guard lock(_lossMtx); _lossHistory.clear(); } _muxTimer.Start(_param.fps, [this] { ++_totalPts; bool anySuccess = false; // 向所有muxer写入数据 { std::lock_guard muxerLock(_muxersMtx); for (const auto& info : _muxers) { if (info.muxer->Write(_encodeFrame, info.streamIndex)) { anySuccess = true; } } } bool loss = !anySuccess; if (loss) ++_lossPts; { std::lock_guard lock(_lossMtx); _lossHistory.push_back(loss); if (_lossHistory.size() > LOSS_WINDOW) _lossHistory.pop_front(); } }); _isRecord = true; return true; } void VideoRecorder::StopRecord() { _isRecord = false; _muxTimer.Stop(); } double VideoRecorder::GetLossRate() { std::lock_guard lock(_lossMtx); if (_lossHistory.size() < LOSS_WINDOW) return -1.0; // 统计中 int lossCount = std::count(_lossHistory.begin(), _lossHistory.end(), true); if (_lossHistory.empty()) { return 0.0; } return double(lossCount) / _lossHistory.size(); } void VideoRecorder::Close() { StopRecord(); _captureTimer.Stop(); _capturer.close(); Free(_encodeFrame, [this] { av_frame_free(&_encodeFrame); }); Free(_renderFrame, [this] { av_frame_free(&_renderFrame); }); } void VideoRecorder::SetCaptureSource(HWND srcHwnd, CaptureMethod method) { // 只切换采集源,不重启编码器和推流 CaptureTarget target; target.type = CaptureTargetType::Window; target.hwnd = srcHwnd; RECT clientRect; if (!GetClientRect(srcHwnd, &clientRect)) return; int width = clientRect.right - clientRect.left; int height = clientRect.bottom - clientRect.top; _capturer.open(target, method, width, height); } void VideoRecorder::SetCaptureSource(int monitorIdx, CaptureMethod method) { // 只切换采集源,不重启编码器和推流 CaptureTarget target; target.type = CaptureTargetType::Monitor; target.monitorIdx = monitorIdx; auto monitorInfo = MonitorFinder::GetList()[monitorIdx]; RECT rect = monitorInfo.rect; int width = rect.right - rect.left; int height = rect.bottom - rect.top; _capturer.open(target, method, width, height); }